Index: Demo/tkinter/guido/kill.py =================================================================== --- Demo/tkinter/guido/kill.py (revision 63551) +++ Demo/tkinter/guido/kill.py (working copy) @@ -4,7 +4,7 @@ from Tkinter import * from string import splitfields from string import split -import commands +import subprocess import os class BarButton(Menubutton): @@ -31,7 +31,7 @@ self.do_update() def do_update(self): name, option, column = self.format_list[self.format.get()] - s = commands.getoutput('ps -w ' + option) + s = subprocess.getoutput('ps -w ' + option) list = splitfields(s, '\n') self.header.set(list[0]) del list[0] Index: Demo/tkinter/guido/svkill.py =================================================================== --- Demo/tkinter/guido/svkill.py (revision 63551) +++ Demo/tkinter/guido/svkill.py (working copy) @@ -9,7 +9,7 @@ from string import splitfields from string import split -import commands +import subprocess import os user = os.environ['LOGNAME'] @@ -46,7 +46,7 @@ def do_update(self): format = self.format_list[self.format.get()][1] view = self.view_list[self.view.get()][1] - s = commands.getoutput('ps %s %s' % (view, format)) + s = subprocess.getoutput('ps %s %s' % (view, format)) list = splitfields(s, '\n') self.header.set(list[0] + ' ') del list[0] Index: Misc/NEWS =================================================================== --- Misc/NEWS (revision 63551) +++ Misc/NEWS (working copy) @@ -48,6 +48,9 @@ Library ------- +- The commands module has been removed. Its methods have been moved in + the subprocess module. + - The repr module has been renamed to reprlib. - The statvfs module has been removed. Index: Misc/cheatsheet =================================================================== --- Misc/cheatsheet (revision 63551) +++ Misc/cheatsheet (working copy) @@ -1816,7 +1816,6 @@ code Utilities needed to emulate Python's interactive interpreter codecs Lookup existing Unicode encodings and register new ones. colorsys Conversion functions between RGB and other color systems. -commands Tools for executing UNIX commands . compileall Force "compilation" of all .py files in a directory. ConfigParser Configuration file parser (much like windows .ini files) copy Generic shallow and deep copying operations. Index: Doc/library/subprocess.rst =================================================================== --- Doc/library/subprocess.rst (revision 63551) +++ Doc/library/subprocess.rst (working copy) @@ -14,7 +14,6 @@ os.system os.spawn* - commands.* Information about how the :mod:`subprocess` module can be used to replace these modules and functions can be found in the following sections. @@ -113,7 +112,7 @@ Convenience Functions ^^^^^^^^^^^^^^^^^^^^^ -This module also defines two shortcut functions: +This module also defines four shortcut functions: .. function:: call(*popenargs, **kwargs) @@ -138,6 +137,35 @@ check_call(["ls", "-l"]) +.. function:: getstatusoutput(cmd) + Return ``(status, output)`` of executing *cmd* in a shell. + + Execute the string *cmd* in a shell with :func:`os.popen` and return a 2-tuple + ``(status, output)``. *cmd* is actually run as ``{ cmd ; } 2>&1``, so that the + returned output will contain output or error messages. A trailing newline is + stripped from the output. The exit status for the command can be interpreted + according to the rules for the C function :cfunc:`wait`. Example:: + + >>> import subprocess + >>> subprocess.getstatusoutput('ls /bin/ls') + (0, '/bin/ls') + >>> subprocess.getstatusoutput('cat /bin/junk') + (256, 'cat: /bin/junk: No such file or directory') + >>> subprocess.getstatusoutput('/bin/junk') + (256, 'sh: /bin/junk: not found') + + +.. function:: getoutput(cmd) + Return output ``(stdout or stderr)`` of executing *cmd* in a shell. + + Like :func:`getstatusoutput`, except the exit status is ignored and the return + value is a string containing the command's output. Example:: + + >>> import subprocess + >>> subprocess.getoutput('ls /bin/ls') + '/bin/ls' + + Exceptions ^^^^^^^^^^ Index: Doc/library/unix.rst =================================================================== --- Doc/library/unix.rst (revision 63551) +++ Doc/library/unix.rst (working copy) @@ -25,4 +25,3 @@ resource.rst nis.rst syslog.rst - commands.rst Index: Lib/test/regrtest.py =================================================================== --- Lib/test/regrtest.py (revision 63551) +++ Lib/test/regrtest.py (working copy) @@ -868,7 +868,6 @@ """ test__locale test_bsddb3 - test_commands test_crypt test_curses test_dbm @@ -910,7 +909,6 @@ test_bsddb test_bsddb3 test_bz2 - test_commands test_crypt test_curses test_dbm @@ -1060,7 +1058,6 @@ """ test_audioop test_bsddb3 - test_commands test_curses test_dl test_epoll Index: Lib/test/test_subprocess.py =================================================================== --- Lib/test/test_subprocess.py (revision 63551) +++ Lib/test/test_subprocess.py (working copy) @@ -702,10 +702,36 @@ p.terminate() self.assertNotEqual(p.wait(), 0) +class CommandTests(unittest.TestCase): +# The module says: +# "NB This only works (and is only relevant) for UNIX." +# +# Actually, getoutput should work on any platform with an os.popen, but +# I'll take the comment as given, and skip this suite. + if os.name == 'posix': + + def test_getoutput(self): + self.assertEquals(subprocess.getoutput('echo xyzzy'), 'xyzzy') + self.assertEquals(subprocess.getstatusoutput('echo xyzzy'), + (0, 'xyzzy')) + + # we use mkdtemp in the next line to create an empty directory + # under our exclusive control; from that, we can invent a pathname + # that we _know_ won't exist. This is guaranteed to fail. + dir = None + try: + dir = tempfile.mkdtemp() + name = os.path.join(dir, "foo") + + status, output = subprocess.getstatusoutput('cat ' + name) + self.assertNotEquals(status, 0) + finally: + if dir is not None: + os.rmdir(dir) + def test_main(): - support.run_unittest(ProcessTestCase) - if hasattr(support, "reap_children"): - support.reap_children() + support.run_unittest(ProcessTestCase, CommandTests) + support.reap_children() if __name__ == "__main__": unittest.main() # XXX test_main() Index: Lib/test/test___all__.py =================================================================== --- Lib/test/test___all__.py (revision 63551) +++ Lib/test/test___all__.py (working copy) @@ -52,7 +52,6 @@ self.check_all("codecs") self.check_all("codeop") self.check_all("colorsys") - self.check_all("commands") self.check_all("compileall") self.check_all("copy") self.check_all("copyreg") Index: Lib/subprocess.py =================================================================== --- Lib/subprocess.py (revision 63551) +++ Lib/subprocess.py (working copy) @@ -17,7 +17,6 @@ os.system os.spawn* -commands.* Information about how the subprocess module can be used to replace these modules and functions can be found below. @@ -105,7 +104,7 @@ (Windows only) -This module also defines two shortcut functions: +This module also defines four shortcut functions: call(*popenargs, **kwargs): Run command with arguments. Wait for command to complete, then @@ -125,6 +124,34 @@ check_call(["ls", "-l"]) +getstatusoutput(cmd): + Return (status, output) of executing cmd in a shell. + + Execute the string 'cmd' in a shell with os.popen() and return a 2-tuple + (status, output). cmd is actually run as '{ cmd ; } 2>&1', so that the + returned output will contain output or error messages. A trailing newline + is stripped from the output. The exit status for the command can be + interpreted according to the rules for the C function wait(). Example: + + >>> import subprocess + >>> subprocess.getstatusoutput('ls /bin/ls') + (0, '/bin/ls') + >>> subprocess.getstatusoutput('cat /bin/junk') + (256, 'cat: /bin/junk: No such file or directory') + >>> subprocess.getstatusoutput('/bin/junk') + (256, 'sh: /bin/junk: not found') + +getoutput(cmd): + Return output (stdout or stderr) of executing cmd in a shell. + + Like getstatusoutput(), except the exit status is ignored and the return + value is a string containing the command's output. Example: + + >>> import subprocess + >>> subprocess.getoutput('ls /bin/ls') + '/bin/ls' + + Exceptions ---------- Exceptions raised in the child process, before the new program has @@ -336,7 +363,8 @@ import fcntl import pickle -__all__ = ["Popen", "PIPE", "STDOUT", "call", "check_call", "CalledProcessError"] +__all__ = ["Popen", "PIPE", "STDOUT", "call", "check_call", "getstatusoutput", + "getoutput", "CalledProcessError"] try: MAXFD = os.sysconf("SC_OPEN_MAX") @@ -458,6 +486,76 @@ return ''.join(result) +# Various tools for executing commands and looking at their output and status. +# +# NB This only works (and is only relevant) for UNIX. + +def getstatusoutput(cmd): + """Return (status, output) of executing cmd in a shell. + + Execute the string 'cmd' in a shell with os.popen() and return a 2-tuple + (status, output). cmd is actually run as '{ cmd ; } 2>&1', so that the + returned output will contain output or error messages. A trailing newline + is stripped from the output. The exit status for the command can be + interpreted according to the rules for the C function wait(). Example: + + >>> import subprocess + >>> subprocess.getstatusoutput('ls /bin/ls') + (0, '/bin/ls') + >>> subprocess.getstatusoutput('cat /bin/junk') + (256, 'cat: /bin/junk: No such file or directory') + >>> subprocess.getstatusoutput('/bin/junk') + (256, 'sh: /bin/junk: not found') + """ + pipe = os.popen('{ ' + cmd + '; } 2>&1', 'r') + text = pipe.read() + sts = pipe.close() + if sts is None: sts = 0 + if text[-1:] == '\n': text = text[:-1] + return sts, text + + +def getoutput(cmd): + """Return output (stdout or stderr) of executing cmd in a shell. + + Like getstatusoutput(), except the exit status is ignored and the return + value is a string containing the command's output. Example: + + >>> import subprocess + >>> subprocess.getoutput('ls /bin/ls') + '/bin/ls' + """ + return getstatusoutput(cmd)[1] + + +def mk2arg(head, x): + """ + Make command argument from directory and pathname (prefix space, add + quotes). + """ + return mkarg(os.path.join(head, x)) + + +def mkarg(x): + """ + Make a shell command argument from a string. + + Return a string beginning with a space followed by a shell-quoted version + of the argument. Two strategies: enclose in single quotes if it contains + none; otherwise, enclose in double quotes and prefix quotable characters + with backslash. + """ + if '\'' not in x: + return ' \'' + x + '\'' + s = ' "' + for c in x: + if c in '\\$"`': + s = s + '\\' + s = s + c + s = s + '"' + return s + + class Popen(object): def __init__(self, args, bufsize=0, executable=None, stdin=None, stdout=None, stderr=None,