Three common ways to call Shell scripts through Python

How to call Shell scripts through Python

This paper introduces three writing methods

  1. Use os.system to run
  2. Use subprocess.run to run
  3. Use subprocess.Popen to run

Advantages and disadvantages of the three methods

os.systemsubprocess.runsubprocess.Popen
Need to resolve parametersnoyesyes
Synchronous execution (waiting for Shell execution results)yesyesno
Can get the input and output of the shellnoyesyes
Shell execution result return valuereturn valueobjectobject

Run through os.system

import os

return_code = os.system('ls -al .')
print("return code:", return_code)

The output of the Shell statement will also be output to the python command console, but the return value that Python can obtain is a number. 0 represents the successful execution of the Shell statement / script, otherwise it represents the status value of the Shell execution. For Shell scripts that do not require detailed return information. The parameters passed into the Shell command are all complete strings.

➜  tmp python test.py
total 8
drwxr-xr-x    3 jinghui.zhang  staff    96 Nov  8 12:29 .
drwxr-xr-x+ 106 jinghui.zhang  staff  3392 Nov  8 12:29 ..
-rwxr-xr-x@   1 jinghui.zhang  staff    82 Nov  8 12:29 test.py
('return code:', 0)

Run through subprocess

It is generally recommended to use the subprocess module to execute shell commands. It can easily control the input and output of shell commands. Unlike os.system, the parameter passed in is an array rather than a string.

import subprocess

return_code = subprocess.run(['ls', '-al', '.'])
print("return code:", return_code)

The returned result of execution is a CompletedProcess object, and the returned result is as follows:

➜  tmp python test.py                                                                                                        
total 8
drwxr-xr-x    3 jinghui.zhang  staff    96 Nov  8 12:34 .
drwxr-xr-x+ 106 jinghui.zhang  staff  3392 Nov  8 12:36 ..
-rwxr-xr-x@   1 jinghui.zhang  staff   103 Nov  8 12:33 test.py
return code: CompletedProcess(args=['ls', '-al', '.'], returncode=0)

If we do not output the result of shell script execution in the console, we can specify stdout of subprocess and ignore it. Such as return_code = subprocess.run(['ls', '-al', '.'], stdout=subprocess.DEVNULL), the output result is only the result of Python program running.

➜  tmp python test.py  
return code: CompletedProcess(args=['ls', '-al', '.'], returncode=0)

If you want to specify the input parameters of the shell command, you can pass them in through the input parameter.

import subprocess

useless_cat_call = subprocess.run(
    ["cat"], stdout=subprocess.PIPE, text=True, input="Hello from the other side")
print(useless_cat_call.stdout)  # Hello from the other side

In the subprocess.run command above:

  • stdout=subprocess.PIPE tells Python to redirect the output of the Shell command, and this part of the output can be called by later Python programs.
  • text=True tells Python to treat stdout and stderr of shell command execution as strings. The default is bytes
  • input="Hello from the other side" tells Python the input parameters of the shell command

The result of the above program is

Hello from the other side

We can enable the execution verification of shell commands. When there is any problem with the execution of the shell, an exception will be thrown.

import subprocess

failed_command = subprocess.run(["false"], check=True)
print("The exit code was: %d" % failed_command.returncode)

Return results

$ python3 false_subprocess.py
Traceback (most recent call last):
  File "false_subprocess.py", line 4, in <module>
    failed_command = subprocess.run(["false"], check=True)
  File "/usr/local/python/3.7.5/Frameworks/Python.framework/Versions/3.7/lib/python3.7/subprocess.py", line 512, in run
    output=stdout, stderr=stderr)
subprocess.CalledProcessError: Command '['false']' returned non-zero exit status 1.

Run through subprocess.Popen

subprocess.run can be regarded as a simplified abstraction of subprocess. Pope. Subprocess. Pope provides greater flexibility.

By default, subprocess.Popen does not pause the Python program itself (asynchronously). But if you have to run synchronously like the previous two methods, you can add the. wait() method.

import subprocess

list_dir = subprocess.Popen(["ls", "-l"])
list_dir.wait()

When we are still in an asynchronous state, how do Python programs know whether the shell command is finished or not? You can poll through poll(). When the result is None, it means that the program is still running. Otherwise, a status code will be returned.

list_dir.poll()

If you want to specify input parameters, you need to use the communicate() method.

import subprocess

useless_cat_call = subprocess.Popen(["cat"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
output, errors = useless_cat_call.communicate(input="Hello from the other side!")
useless_cat_call.wait()
print(output)
print(errors)

The. communicate method also returns standard input and standard output. See the official website for more details https://docs.python.org/3/library/subprocess.html .

Reference documents

  1. Executing Shell Commands with Python

Keywords: Python shell Back-end

Added by Dilbert137 on Mon, 08 Nov 2021 06:24:53 +0200