How to call Shell scripts through Python
This paper introduces three writing methods
- Use os.system to run
- Use subprocess.run to run
- Use subprocess.Popen to run
Advantages and disadvantages of the three methods
os.system | subprocess.run | subprocess.Popen | |
---|---|---|---|
Need to resolve parameters | no | yes | yes |
Synchronous execution (waiting for Shell execution results) | yes | yes | no |
Can get the input and output of the shell | no | yes | yes |
Shell execution result return value | return value | object | object |
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