Index: Doc/lib/libsubprocess.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/lib/libsubprocess.tex,v retrieving revision 1.4 diff -u -r1.4 libsubprocess.tex --- Doc/lib/libsubprocess.tex 5 Dec 2004 20:15:36 -0000 1.4 +++ Doc/lib/libsubprocess.tex 13 Dec 2004 02:52:24 -0000 @@ -120,7 +120,7 @@ \subsubsection{Convenience Functions} -This module also defines one shortcut function: +This module also defines two shortcut functions: \begin{funcdesc}{call}{*popenargs, **kwargs} Run command with arguments. Wait for command to complete, then @@ -133,6 +133,18 @@ \end{verbatim} \end{funcdesc} +\begin{funcdesc}{check_call}{*popenargs, **kwargs} +Run command with arguments. Wait for command to complete. If the exit +code was zero then return, otherwise raise CalledProcessError. The +CalledProcessError object will have the return code in the +\member{errno} attribute. + +The arguments are the same as for the Popen constructor. Example: + +\begin{verbatim} + check_call(["ls", "-l"]) +\end{verbatim} +\end{funcdesc} \subsubsection{Exceptions} @@ -149,6 +161,10 @@ A \exception{ValueError} will be raised if \class{Popen} is called with invalid arguments. +check_call() will raise \exception{CalledProcessError}, which is a +subclass of \exception{OSError}, if the called process returns a +non-zero return code. + \subsubsection{Security} Index: Lib/subprocess.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/subprocess.py,v retrieving revision 1.11 diff -u -r1.11 subprocess.py --- Lib/subprocess.py 5 Dec 2004 20:15:36 -0000 1.11 +++ Lib/subprocess.py 13 Dec 2004 02:52:24 -0000 @@ -133,6 +133,15 @@ retcode = call(["ls", "-l"]) +check_call(*popenargs, **kwargs): + Run command with arguments. Wait for command to complete. If the + exit code was zero then return, otherwise raise + CalledProcessError. The CalledProcessError object will have the + return code in the errno attribute. + + The arguments are the same as for the Popen constructor. Example: + + check_call(["ls", "-l"]) Exceptions ---------- @@ -148,6 +157,9 @@ A ValueError will be raised if Popen is called with invalid arguments. +check_call() will raise CalledProcessError, which is a subclass of +OSError, if the called process returns a non-zero return code. + Security -------- @@ -363,6 +375,13 @@ import types import traceback +# Exception classes used by this module. +class CalledProcessError(OSError): + """This exception is raised when a process run by check_call() returns + a non-zero exit status. The exit status will be stored in the + errno attribute. This exception is a subclass of + OSError.""" + if mswindows: import threading import msvcrt @@ -393,7 +412,7 @@ import fcntl import pickle -__all__ = ["Popen", "PIPE", "STDOUT", "call"] +__all__ = ["Popen", "PIPE", "STDOUT", "call", "check_call", "CalledProcessError"] try: MAXFD = os.sysconf("SC_OPEN_MAX") @@ -428,6 +447,25 @@ return Popen(*popenargs, **kwargs).wait() +def check_call(*popenargs, **kwargs): + """Run command with arguments. Wait for command to complete. If + the exit code was zero then return, otherwise raise + CalledProcessError. The CalledProcessError object will have the + return code in the errno attribute. + + The arguments are the same as for the Popen constructor. Example: + + check_call(["ls", "-l"]) + """ + retcode = call(*popenargs, **kwargs) + cmd = kwargs.get("args") + if cmd is None: + cmd = popenargs[0] + if retcode: + raise CalledProcessError(retcode, "Command %s returned non-zero exit status" % cmd) + return retcode + + def list2cmdline(seq): """ Translate a sequence of arguments into a command line Index: Lib/test/test_subprocess.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/test/test_subprocess.py,v retrieving revision 1.16 diff -u -r1.16 test_subprocess.py --- Lib/test/test_subprocess.py 30 Nov 2004 21:04:45 -0000 1.16 +++ Lib/test/test_subprocess.py 13 Dec 2004 02:52:24 -0000 @@ -44,6 +44,22 @@ "import sys; sys.exit(47)"]) self.assertEqual(rc, 47) + def test_check_call_zero(self): + # check_call() function with zero return code + rc = subprocess.check_call([sys.executable, "-c", + "import sys; sys.exit(0)"]) + self.assertEqual(rc, 0) + + def test_check_call_nonzero(self): + # check_call() function with non-zero return code + try: + subprocess.check_call([sys.executable, "-c", + "import sys; sys.exit(47)"]) + except subprocess.CalledProcessError, e: + self.assertEqual(e.errno, 47) + else: + self.fail("Expected CalledProcessError") + def test_call_kwargs(self): # call() function with keyword args newenv = os.environ.copy()