当前subprocess对我来说主要就是用来替换一个老的os.system/os.popen的作用。
调用subprocess的推荐方法是对于它可以处理的所有使用场景都使用run()
函数。对于更高级的使用场景,可以直接使用底层的Popen
接口
对subprocess的主要函数和数做了一个思维导图
如果仅是想得调用系统命令的(output, returncode),我推荐的用法为:
1. subprocess.getstatusoutput(cmd)
2. subprocess.run(cmd, capture_output=True, shell=True, encoding='utf-8')
3. Popen(cmd, stdout=PIPE, encoding='utf-8', shell=True).communicate()[0]
1.是最简单的
2.是官方推荐的
3.是更底层,更麻烦一点。
以下是一些实例和说明(注:当前测试均为在windows10+python3.7.2 64bit进行的):
subprocess.run
(args, *, stdin=None, input=None, stdout=None, stderr=None, capture_output=False, shell=False, cwd=None, timeout=None, check=False, encoding=None, errors=None, text=None, env=None, universal_newlines=None)
In [2]: import subprocess
In [3]: from subprocess import Popen, PIPE
In [4]: subprocess.run('adb devices', capture_output=True, shell=True, encoding='gbk')
Out[4]: CompletedProcess(args='adb devices', returncode=0, stdout='List of devices attached\nad17caf5\tdevice\n\n', stde
rr='')
In [5]: s = subprocess.run('adb devices', capture_output=True, shell=True, encoding='gbk')
In [6]: s.stdout
Out[6]: 'List of devices attached\nad17caf5\tdevice\n\n'
In [7]: s.stdout.splitlines()
Out[7]: ['List of devices attached', 'ad17caf5\tdevice', '']
In [26]: subprocess.run('adb devices', capture_output=True, shell=True, encoding='gbk')
Out[26]: CompletedProcess(args='adb devices', returncode=0, stdout='List of devices attached\nad17caf5\tdevice\n\n', std
err='')
In [28]: s.args
Out[28]: 'adb devices'
In [29]: s.returncode
Out[29]: 0
In [30]: s.stderr
Out[30]: ''
subprocess.run函数在使用时,需要注意的是,如果执行结果包括中文,但encoding='utf-8'时就会报错,这时,需要将encoding='gbk', 当前我也不清楚为何会这样. eg:
In [10]: s = subprocess.run('dir', capture_output=True, shell=True, encoding='utf-8')
会报以下错误:
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xc7 in position 1: invalid continuation byte
- subpocess.getstatusoutput(cmd) 返回执行结果的tuple(status,output)
In [21]: status, output = subprocess.getstatusoutput('adb devices')
In [22]: status
Out[22]: 0
In [23]: output
Out[23]: 'List of devices attached\nad17caf5\tdevice\n'
In [24]: type(output)
Out[24]: str
-
subprocess.
Popen
(args, bufsize=-1, executable=None, stdin=None, stdout=None, stderr=None, preexec_fn=None, close_fds=True, shell=False, cwd=None, env=None, universal_newlines=None, startupinfo=None, creationflags=0, restore_signals=True, start_new_session=False, pass_fds=(), *, encoding=None, errors=None, text=None)
In [48]: s = Popen('adb devices', stdout=PIPE, shell=True, encoding='utf-8')
In [49]: stdout_data, stderr_data = s.communicate()
In [50]: stdout_data
Out[50]: 'List of devices attached\nad17caf5\tdevice\n\n'
In [51]: stderr_data
In [52]: type(s)
Out[52]: subprocess.Popen