1. subprocess.run()方法
subprocess.run(args, *, stdin=None, input=None, stdout=None, stderr=None, shell=False, cwd=None, timeout=None, check=False, encoding=None, errors=None)
该函数返回一个CompletedProcess类(有属性传入参数及返回值)的实例。
- args 代表需要在操作系统中执行的命令,可以是字符串形式(要求shell=True),也可以是列表list类型。
- * 代表可变参数,一般是列或字典形式。
- stdin、stdout、stderr 指定了可执行程序的标准输入、标准输出、标准错误文件句柄。
- shell 代表着程序是否需要在shell上执行,当想使用shell的特性时,设置shell=True,这样就可以使用shell指令的管道、文件名称通配符、环境变量等,不过Python也提供了许多类shell的模块,如glob、fnmatch、os.walk()、os.path.expandvars()、os.path.expanduser()和shutil。
- check 如果check设置为True,就检查命令的返回值,当返回值为非0时,将抛出CalledProcessError异常。
- timeout 设置超时时间,如果超时,则强制kill掉子进程。
示例1:在Linux系统中执行一个脚本并获取它的返回值。
方法一:
>>> import subprocess
>>> a=subprocess.run("ls -l /dev/null", shell=True)
crw-rw-rw-. 1 root root 1, 3 Feb 7 17:53 /dev/null
>>> a
CompletedProcess(args='ls -l /dev/null', returncode=0)
>>> a.args
'ls -l /dev/null'
>>> a.returncode
0
方法二:
>>> import subprocess
>>> b=subprocess.run(["ls","-l","/dev/null"])
crw-rw-rw-. 1 root root 1, 3 Feb 7 17:53 /dev/null
>>> b
CompletedProcess(args=['ls', '-l', '/dev/null'], returncode=0)
>>> b.args
['ls', '-l', '/dev/null']
>>> b.returncode
0
如果要捕获脚本的输出,可以使用以下方法:
>>> a=subprocess.run(["ls","-l","/dev/null"],stdout=subprocess.PIPE)
>>> a
CompletedProcess(args=['ls', '-l', '/dev/null'], returncode=0, stdout=b'crw-rw-rw-. 1 root root 1, 3 Feb 7 17:53 /dev/null\n')
>>> a.stdout
b'crw-rw-rw-. 1 root root 1, 3 Feb 7 17:53 /dev/null\n'
如果传入参数check=True,当returncode不为0时,将会抛出subprocess.CalledProcessError异常;如果传输timeout参数,当运行时间超过timeout时就会抛出TimeoutExpired异常。运行结果如下:
>>> a=subprocess.run("exit 1",check=True)
Traceback (most recent call last):
File "", line 1, in
File "/usr/local/python3.6.5/lib/python3.6/subprocess.py", line 403, in run
with Popen(*popenargs, **kwargs) as process:
File "/usr/local/python3.6.5/lib/python3.6/subprocess.py", line 709, in __init__
restore_signals, start_new_session)
File "/usr/local/python3.6.5/lib/python3.6/subprocess.py", line 1344, in _execute_child
raise child_exception_type(errno_num, err_msg, err_filename)
FileNotFoundError: [Errno 2] No such file or directory: 'exit 1': 'exit 1'
>>> a=subprocess.run("exit 1",shell=True,check=True)
Traceback (most recent call last):
File "", line 1, in
File "/usr/local/python3.6.5/lib/python3.6/subprocess.py", line 418, in run
output=stdout, stderr=stderr)
subprocess.CalledProcessError: Command 'exit 1' returned non-zero exit status 1.
>>> a=subprocess.run("sleep 3",shell=True,timeout=2)
Traceback (most recent call last):
File "/usr/local/python3.6.5/lib/python3.6/subprocess.py", line 405, in run
stdout, stderr = process.communicate(input, timeout=timeout)
File "/usr/local/python3.6.5/lib/python3.6/subprocess.py", line 843, in communicate
stdout, stderr = self._communicate(input, endtime, timeout)
File "/usr/local/python3.6.5/lib/python3.6/subprocess.py", line 1540, in _communicate
self.wait(timeout=self._remaining_time(endtime))
File "/usr/local/python3.6.5/lib/python3.6/subprocess.py", line 1449, in wait
raise TimeoutExpired(self.args, timeout)
subprocess.TimeoutExpired: Command 'sleep 3' timed out after 1.9998847030074103 seconds
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "", line 1, in
File "/usr/local/python3.6.5/lib/python3.6/subprocess.py", line 410, in run
stderr=stderr)
subprocess.TimeoutExpired: Command 'sleep 3' timed out after 2 seconds
一个任务不确定什么时间完成,可以设置一个超时时间,如果超时仍未完成,可以通过代码控制超时重新运行。如果超时重试3次不成功,就让程序报错退出。
2. Popen类
Popen类的构造函数
class subprocess.Popen( args,
bufsize=0,
executable=None,
stdin=None,
stdout=None,
stderr=None,
preexec_fn=None,
close_fds=False,
shell=False,
cwd=None,
env=None,
universal_newlines=False,
startupinfo=None,
creationflags=0)
使用方法如下:
subprocess.Popen(["cat","abc.txt"])
subprocess.Popen("cat abc.txt")
这两个方法,后者将不会工作。因为如果是一个字符串的话,就必须是程序的路径才可以。(考虑unix的api函数exec,接受的是字符串列表)。但是下面的可以工作:
subprocess.Popen("cat abc.txt",shell=True)
这是因为它相当于:
subprocess.Popen(["/bin/sh","-c","cat abc.txt"])
3. 其他方法
(1)subprocess.call(*popenargs,**kwargs):call方法调用Popen()执行程序,并等待它完成。
(2)subprocess.check_call(*popenargs,**kwargs):调用前面的call(),如果返回值非零,则抛出异常。
(3)subprocess.check_output(*popenargs,**kwargs):调用Popen()执行程序,并返回其标准输出。