Python: Make System Call
Call Shell Command, Wait, Get Output
subprocess.check_output([cmd, arg1, arg2, etc])
- Run shell command. Wait for command to finish, then return its output. If the exit code is not 0, then raises CalledProcessError.
# call unix shell command and get its output import subprocess output = subprocess.check_output(["ls", "-al"]) print(output.decode("utf-8"))
Call Shell Command, Wait, Ignore Output, Get Exit Code
subprocess.call([cmd, arg1, arg2, etc])
- Run shell command. Wait for command to finish, then return the shell command exit code.
# call unix shell command and get its exit code. (ignore output) import subprocess exitCode = subprocess.call(["ls", "-al"]) print(exitCode)
subprocess.call()
will run successfully even if the shell command did not run successfully.
# call unix shell command and get its exit code. import subprocess # here, ls will exit with error code 2, because there is no option -y exitCode = subprocess.call(["ls", "-y"]) # python will not raise error print exitCode # 2
(Linux shell commands have exit code of 0 if ran successfully.)
Call Shell Command, Ignore Output, Stop on Error
subprocess.check_call([cmd, arg1, arg2, etc])
-
Run shell command. Wait for command to finish. If the return code is 0 then return 0, else raise CalledProcessError. To get exit code, call
CalledProcessError.returncode
.
# call unix shell command. Raise exception if the command failed import subprocess # ls does not have -y option exitCode = subprocess.check_call(["ls", "-y"]) # this will not be printed print("done") # python exit error # ls: illegal option -- y # usage: ls [-ABCFGHLOPRSTUWabcdefghiklmnopqrstuwx1] [file ...]
Advanced: subprocess.Popen()
All the following commands:
subprocess.call(…)
subprocess.check_call(…)
subprocess.check_output(…)
are wrappers to the more general function subprocess.Popen()
. Here's the code:
def call(*popenargs, **kwargs): """Run command with arguments. Wait for command to complete, then return the returncode attribute. The arguments are the same as for the Popen constructor. Example: retcode = call(["ls", "-l"]) """ 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 returncode attribute. The arguments are the same as for the Popen constructor. Example: check_call(["ls", "-l"]) """ retcode = call(*popenargs, **kwargs) if retcode: cmd = kwargs.get("args") if cmd is None: cmd = popenargs[0] raise CalledProcessError(retcode, cmd) return 0
def check_output(*popenargs, **kwargs): r"""Run command with arguments and return its output as a byte string. If the exit code was non-zero it raises a CalledProcessError. The CalledProcessError object will have the return code in the returncode attribute and output in the output attribute. The arguments are the same as for the Popen constructor. Example: >>> check_output(["ls", "-l", "/dev/null"]) 'crw-rw-rw- 1 root root 1, 3 Oct 18 2007 /dev/null\n' The stdout argument is not allowed as it is used internally. To capture standard error in the result, use stderr=STDOUT. >>> check_output(["/bin/sh", "-c", ... "ls -l non_existent_file ; exit 0"], ... stderr=STDOUT) 'ls: non_existent_file: No such file or directory\n' """ if 'stdout' in kwargs: raise ValueError('stdout argument not allowed, it will be overridden.') process = Popen(stdout=PIPE, *popenargs, **kwargs) output, unused_err = process.communicate() retcode = process.poll() if retcode: cmd = kwargs.get("args") if cmd is None: cmd = popenargs[0] raise CalledProcessError(retcode, cmd, output=output) return output
Examples of using: subprocess.Popen()
Call and Don't Wait
Suppose you want to decompress a file. gzip -d x.txt.gz
import subprocess # call a unix command but not wait for it to finish subprocess.Popen([r"gzip","-d", "x.txt.gz"])
Call and Wait for Command to Finish
Suppose you want to decompress a file. gzip -d x.txt.gz
import subprocess subprocess.Popen([r"gzip","-d", "x.txt.gz"]).wait()
The subprocess.Popen([…])
creates a object. The .wait()
makes the code wait until the system call finished.
Get Output
To make a system call and get its output, pass the argument stdout=subprocess.PIPE
, and get output from the method communicate()[0]
.
import subprocess # call a unix command, wait for it to finish, get its output myOutput=subprocess.Popen([r"tail","-n 1", "x.txt"], stdout=subprocess.PIPE).communicate()[0]
The method communicate()
returns a tuple (stdoutdata, stderrdata), but you must pass arguments stdout=subprocess.PIPE
and stderr=subprocess.PIPE
to subprocess.Popen()
.
Full Example
Following is a complete example. The code makes a system call to decompress a gzip file (and wait for it), then get the last line of the file by calling the unix util “tail”, then gzip the file again.
import subprocess # decompress a file subprocess.Popen([r"gzip","-d", "x.txt.gz"]).wait() # get last line last_line = subprocess.Popen([r"tail","-n 1", "x.txt"], stdout=subprocess.PIPE).communicate()[0] # compress the file subprocess.Popen([r"gzip","x.txt"]) print(last_line)
Note: Python has a gzip module. If you really want to compress/decompress a file, use that. 〔see Python: Compress/Decompress Gzip Files〕
Get Output, Stderr, Exit Code, Process Id
Here's a example of getting both output and exit code.
import subprocess # call shell command subP = subprocess.Popen(["du", "--si", "-s", "/usr/bin"], stdout=subprocess.PIPE , stderr=subprocess.PIPE) stdout, stderr = subP.communicate() exitCode = subP.returncode pid = subP.pid print("--------------------\n output is:", stdout) print("--------------------\n stderr is:", stderr) print("--------------------\n exit code is:", exitCode) print("--------------------\n pid is:", pid)