The Subprocess.run Method
The Subprocess.run method takes a list of arguments. When the method is called, it executes the command and waits for the process to finish, returning a βCompletedProcessβ object in the end. The βCompletedProcessβ object returns stdout, stderr, original arguments used while calling the method, and a return code. Stdout refers to the data stream produced by the command, while stderr refers to any errors raised during execution of the program. Any non-zero return code (exit code) would mean error with the command executed in the subprocess.run method.
Example 1: Output Contents of A Text File Using the Subprocess.run Method
The command below will output the contents of a βdata.txtβ file, assuming that it contains a βname=Johnβ string.
subprocess.run(["cat", "data.txt"])
Running the code above will return the following output:
CompletedProcess(args=['cat', 'data.txt'], returncode=0)
The first element of the list argument is the name of the command to be executed. Any element in the list that follows the first element are considered command-line options or switches. You can use single dash and double dashes, as well, to define the options. For example, to list files and folders in a directory, the code would be βsubprocess.run([“ls”, “-l”]β. In most of these cases, you can consider any space-separated argument in a shell command as an individual element in the list supplied to the subprocess.run method.
Example 2: Suppress Output of Subprocess.run Method
To suppress the output of the subprocess.run method, you will have to supply βstdout=subprocess.DEVNULLβ and βstderr=subprocess.DEVNULLβ as additional arguments.
subprocess.run(["cat", "data.txt"], stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL)
Running the code above will produce the following output:
Example 3: Capture Output of Subprocess.run Method
To capture the output of the subprocess.run method, use an additional argument named βcapture_output=Trueβ.
output = subprocess.run(["cat", "data.txt"], capture_output=True)
print (output)
Running the code above will produce the following output:
stdout=b'name=John\n', stderr=b'')
You can individually access stdout and stderr values by using βoutput.stdoutβ and βoutput.stderrβ methods. The output is produced as a byte sequence. To get a string as output, use βoutput.stdout.decode(“utf-8”)β method. You can also supply βtext=Trueβ as an extra argument to the subprocess.run call to get the output in string format. To get exit status code, you can use the βoutput.returncodeβ method.
Example 4: Raise Exception on Failure of Command Executed by Subprocess.run Method
To raise an exception when the command exits with a non-zero status, use the βcheck=Trueβ argument.
subprocess.run(["cat", "data.tx"], capture_output=True, text=True, check=True)
Running the code above will produce the following output:
subprocess.CalledProcessError: Command '['cat', 'data.tx']'
returned non-zero exit status 1.
Example 5: Pass a String to Command Executed by the Subprocess.run Method
You can pass a string to the command to be executed by subprocess.run method by using βinput=βstringββ argument.
output = subprocess.run(["cat"], input="data.txt", capture_output=True,
text=True, check=True)
print (output)
Running the code above will produce the following output:
As you can see, the code above passes βdata.txtβ as a string and not as a file object. To pass βdata.txtβ as a file, use the βstdinβ argument.
output = subprocess.run(["cat"], stdin=f, capture_output=True,
text=True, check=True)
print (output)
Running the code above will produce the following output:
Example 6: Execute Command Directly in Shell Using the Subprocess.run Method
It is possible to run a command directly into a shell βas is,β instead of using a string split in the main command and the options that follow it. To do this, you must pass βshell=Trueβ as an additional argument. This is however, discouraged by python developers as using βshell=Trueβ can lead to security issues. You can read more about security implications from here.
subprocess.run("cat 'data.txtβ", shell=True)
Running the code above will produce the following output:
Conclusion
The subprocess.run method in Python is pretty powerful, as it allows you to run shell commands within python itself. This helps in limiting all code to python itself without the need to have additional shell script code in separate files. It can be, however, quite tricky to correctly tokenize shell commands in a python list. You can use the βshlex.split()β method to tokenize simple shell commands, but in long, complex commands β especially those with pipe symbols β shlex fails to correctly split the command. In such cases, debugging can be a tricky issue. You can use the βshell=Trueβ argument to avoid this, but there are certain security concerns associated with this action.