Link Search Menu Expand Document

Start a process in Python

Start a process in Python

Sometimes you might want to spawn a process from python and interact with the data. You might use a process to generate some files that your python application will read, or read the output of the process within your application. Doing so is relatively simple in python using the subprocess library,.

subprocess.Popen

You can start a process in Python using the Popen function call. Open a pipe to or from command. The return value is an open file object connected to the pipe, which can be read or written depending on whether mode is ‘r’ (default) or ‘w’.

from subprocess import Popen, PIPE
process = Popen(['cat', 'scores.csv'], stdout=PIPE, stderr=PIPE)
stdout, stderr = process.communicate()
print(stdout.decode('utf-8'))

The process.communicate() call reads input and output from the process. stdout is the process output. stderr will be written only if an error occurs. If you want to wait for the program to finish you can call Popen.wait().

from subprocess import Popen, PIPE
 
process = Popen(['cat', 'scores.csv'], stdout=PIPE, stderr=PIPE)
stdout, stderr = process.communicate()
status = process.wait()
print(stdout.decode('utf-8'))

subprocess.call

Subprocess has a method call() which can be used to start a program. This is basically just like the Popen class and takes all of the same arguments, but it simply wait until the command completes and gives us the return code.

import subprocess
subprocess.call(['ls','-l'])
total 192
-rw-r--r--  1 bk  staff   7977 Oct 21 09:46 01 - Getting Started.ipynb
-rw-r--r--  1 bk  staff   7400 Oct 17 20:44 02 - Terminal Application.ipynb
-rw-r--r--  1 bk  staff  10581 Oct 17 20:44 03 - Argparse.ipynb
-rw-r--r--  1 bk  staff  14711 Oct 17 20:44 04 - Start a process in Python.ipynb
-rw-r--r--  1 bk  staff    149 Aug 26 15:35 argparse_1.py
-rw-r--r--  1 bk  staff    202 Aug 26 15:35 argparse_2.py
-rw-r--r--  1 bk  staff    299 Aug 26 15:35 argparse_3.py
-rw-r--r--  1 bk  staff    309 Aug 26 15:35 argparse_4.py
-rw-r--r--  1 bk  staff    219 Aug 26 15:35 argparse_5.py
-rw-r--r--  1 bk  staff    580 Aug 26 15:35 argparse_6.py
-rw-r--r--  1 bk  staff    372 Aug 26 15:35 terminal_1.py
-rw-r--r--  1 bk  staff    370 Aug 26 15:35 terminal_2.py
-rw-r--r--  1 bk  staff    198 Aug 26 15:35 test_class.py
-rw-r--r--  1 bk  staff    100 Aug 26 15:35 test_sample.py
-rw-r--r--  1 bk  staff    143 Aug 26 15:35 test_sysexit.py
-rw-r--r--  1 bk  staff     90 Oct 17 20:44 test_tmpdir.p




0



y
-rw-r--r--  1 bk  staff    294 Oct 17 20:44 test_tmppath.py
total 181
drwxr-xr-x    2 root root  4096 Mar  3  2012 bin
drwxr-xr-x    4 root root  1024 Oct 26  2012 boot

The command line arguments are passed as a list of strings, which avoids the need for escaping quotes or other special characters that might be interpreted by the shell.

subprocess.check_call()

The check_call() function works like call() except that the exit code is checked, and if it indicates an error happened then a CalledProcessError exception is raised.

import subprocess
subprocess.check_call(['false'])
---------------------------------------------------------------------------

CalledProcessError                        Traceback (most recent call last)

/var/folders/jd/pq0swyt521jb2424d6fvth840000gn/T/ipykernel_91211/359612823.py in <module>
      1 import subprocess
----> 2 subprocess.check_call(['false'])


~/opt/miniconda3/envs/cmu39/lib/python3.9/subprocess.py in check_call(*popenargs, **kwargs)
    371         if cmd is None:
    372             cmd = popenargs[0]
--> 373         raise CalledProcessError(retcode, cmd)
    374     return 0
    375 


CalledProcessError: Command '['false']' returned non-zero exit status 1.

subprocess.check_output()

The standard input and output channels for the process started by call() are bound to the parent’s input and output. That means the calling program cannot capture the output of the command. To capture the output, we can use check_output() for later processing.

import subprocess
output = subprocess.check_output(['ls','-l'])
print(output.decode('utf-8'))
total 192
-rw-r--r--  1 bk  staff   7977 Oct 21 09:46 01 - Getting Started.ipynb
-rw-r--r--  1 bk  staff   7400 Oct 17 20:44 02 - Terminal Application.ipynb
-rw-r--r--  1 bk  staff  10581 Oct 17 20:44 03 - Argparse.ipynb
-rw-r--r--  1 bk  staff  14711 Oct 17 20:44 04 - Start a process in Python.ipynb
-rw-r--r--  1 bk  staff    149 Aug 26 15:35 argparse_1.py
-rw-r--r--  1 bk  staff    202 Aug 26 15:35 argparse_2.py
-rw-r--r--  1 bk  staff    299 Aug 26 15:35 argparse_3.py
-rw-r--r--  1 bk  staff    309 Aug 26 15:35 argparse_4.py
-rw-r--r--  1 bk  staff    219 Aug 26 15:35 argparse_5.py
-rw-r--r--  1 bk  staff    580 Aug 26 15:35 argparse_6.py
-rw-r--r--  1 bk  staff    372 Aug 26 15:35 terminal_1.py
-rw-r--r--  1 bk  staff    370 Aug 26 15:35 terminal_2.py
-rw-r--r--  1 bk  staff    198 Aug 26 15:35 test_class.py
-rw-r--r--  1 bk  staff    100 Aug 26 15:35 test_sample.py
-rw-r--r--  1 bk  staff    143 Aug 26 15:35 test_sysexit.py
-rw-r--r--  1 bk  staff     90 Oct 17 20:44 test_tmpdir.py
-rw-r--r--  1 bk  staff    294 Oct 17 20:44 test_tmppath.py