subprocess
subprocess — Subprocess management
2.4版本中的新功能。
该subprocess
模块允许你产生新的进程,连接到他们的输入/输出/错误管道,并获得他们的返回代码。该模块旨在替换几个较旧的模块和功能:
os.system
os.spawn*
os.popen*
popen2.*
commands.*
有关如何使用此模块替换旧功能的信息可以在子流程替换部分找到。
1.使用子流程模块
推荐子程序的推荐方法是使用以下便利功能。对于更高级的用例,如果这些用例不能满足您的需求,请使用基础Popen
接口。
subprocess.call(args, *, stdin=None, stdout=None, stderr=None, shell=False)
运行args
描述的命令。等待命令完成,然后返回returncode
属性。
上面显示的参数仅仅是最常用的参数,在下面的常用参数中进行了描述(因此缩写签名中的略带奇数的记号)。完整的函数签名与Popen
构造函数的签名相同- 该函数将所有提供的参数直接传递到该接口。
例子:
>>> subprocess.call(["ls", "-l"])
0
>>> subprocess.call("exit 1", shell=True)
1
警告
使用shell=True
可能是安全隐患。有关详细信息,请参阅常用参数下的警告。
注意
不要使用stdout=PIPE
或stderr=PIPE
使用此功能,因为它可能会基于子进程输出量导致死锁。在需要管道时使用Popen
该communicate()
方法。
subprocess.check_call(args, *, stdin=None, stdout=None, stderr=None, shell=False)
带参数运行命令。等待命令完成。如果返回码为零,则返回,否则提升CalledProcessError
。该CalledProcessError
对象将在returncode
属性中具有返回码。
上面显示的参数仅仅是最常用的参数,在下面的常用参数中进行了描述(因此缩写签名中的略带奇数的记号)。完整的函数签名与Popen
构造函数的签名相同- 该函数将所有提供的参数直接传递到该接口。
例子:
>>> subprocess.check_call(["ls", "-l"])
0
>>> subprocess.check_call("exit 1", shell=True)
Traceback (most recent call last):
...
subprocess.CalledProcessError: Command 'exit 1' returned non-zero exit status 1
2.5版本中的新功能。
警告
使用shell=True
可能是安全隐患。有关详细信息,请参阅常用参数下的警告。
注意
不要使用stdout=PIPE
或stderr=PIPE
使用此功能,因为它可能会基于子进程输出量导致死锁。在需要管道时使用Popen
该communicate()
方法。
subprocess.check_output(args, *, stdin=None, stderr=None, shell=False, universal_newlines=False)
使用参数运行命令并将其输出作为字节字符串返回。
如果返回代码不为零,则会引发一次CalledProcessError
。该CalledProcessError
对象将在returncode
属性中具有返回码,并在属性中包含任何输出output
。
上面显示的参数仅仅是最常用的参数,在下面的常用参数中进行了描述(因此缩写签名中的略带奇数的记号)。完整的函数签名与Popen
构造函数的签名基本相同,只是stdout
不允许在内部使用。所有其他提供的参数都直接传递给Popen
构造函数。
例子:
>>> subprocess.check_output(["echo", "Hello World!"])
'Hello World!\n'
>>> subprocess.check_output("exit 1", shell=True)
Traceback (most recent call last):
...
subprocess.CalledProcessError: Command 'exit 1' returned non-zero exit status 1
要在结果中捕获标准错误,请使用stderr=subprocess.STDOUT
:
>>> subprocess.check_output(
... "ls non_existent_file; exit 0",
... stderr=subprocess.STDOUT,
... shell=True)
'ls: non_existent_file: No such file or directory\n'
2.7版本的新功能。
警告
使用shell=True
可能是安全隐患。有关详细信息,请参阅常用参数下的警告。
注意
请勿使用stderr=PIPE
此功能,因为可能会因子进程错误量而导致死锁。当你需要一个stderr管道时使用Popen
该communicate()
方法。
subprocess.PIPE
特殊值,可用作标准输入
,标准输出
或标准错误
参数,Popen
并指示应打开标准流的管道。
subprocess.STDOUT
可以用作stderr
参数的特殊值,Popen
并指示标准错误应该与标准输出进入相同的句柄。
exception subprocess.CalledProcessError
当进程运行check_call()
或check_output()
返回非零退出状态时引发异常。
returncode
退出子进程的状态。
cmd
用于产生子进程的命令。
output
子进程的输出,如果这个异常被引发check_output()
。否则,None
。
1.1。常用参数
为了支持各种各样的用例,Popen
构造函数(和便利函数)接受大量的可选参数。对于大多数典型的用例,这些参数中的很多可以安全地保留其默认值。最常见的论据是:
所有调用都需要args
,并且应该是一个字符串或一系列程序参数。提供一系列参数通常是首选的,因为它允许模块处理任何所需的参数转义和引用(例如允许文件名中的空格)。如果传递一个字符串,则shell
必须是True
(见下文),否则字符串必须简单地命名要执行的程序而不指定任何参数。
stdin
,stdout
和stderr分别
指定执行的程序的标准输入,标准输出和标准错误文件句柄。有效值是PIPE
一个现有的文件描述符(一个正整数),一个现有的文件对象,和None
。PIPE
表示应该创建一个新的管道给孩子。使用默认设置None
,不会发生重定向; 孩子的文件句柄将从父类继承。此外,stderr
可以是STDOUT
,这表示应该将stderr
数据从子进程捕获到与stdout
相同的文件句柄中。
当stdout
或stderr
是管道并且universal_newlines时
,True
则所有行结束符都将转换'\n'
为对通用换行符 'U'
模式参数所述open()
。
如果shell
是True
,则指定的命令将通过shell
执行。如果您主要将Python用于其在大多数系统shell
中提供的增强控制流并且仍希望方便地访问其他shell
功能,如shell
管道,文件名通配符,环境变量扩展以及扩展~
到用户的主目录。但是请注意,Python本身提供了很多贝壳般的功能实现(特别是glob
,fnmatch
,os.walk()
,os.path.expandvars()
,os.path.expanduser()
,和shutil
)。
警告
执行包含来自不可信源的未经处理的输入的shell命令会使程序容易受到shell注入的攻击,这是一个严重的安全漏洞,可导致任意命令执行。出于这个原因,使用shell=True
被强烈反对
在命令字符串是从外部输入的情况下构造:
>>> from subprocess import call
>>> filename = input("What file would you like to display?\n")
What file would you like to display?
non_existent; rm -rf / #
>>> call("cat " + filename, shell=True) # Uh-oh. This will end badly...
shell=False
禁用所有基于shell的功能,但不受此漏洞的影响; 请参阅Popen
构造函数文档中的注释以获取有用的提示shell=False
。
在使用时shell=True
,pipes.quote()
可用于正确地转义要用于构造shell命令的字符串中的空白和shell元字符。
这些选项以及所有其他选项在Popen
构造函数文档中有更详细的描述。
1.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)
在新过程中执行子程序。在Unix上,类使用os.execvp()
类行为来执行子程序。在Windows上,该类使用Windows CreateProcess()
功能。参数Popen
如下。
参数
应该是一系列程序参数
或者一个字符串。默认情况下,如果args
是一个序列,则要
执行的程序是args中
的第一个项目。如果args
是一个字符串,则解释是依赖于平台的,并在下面进行描述。查看shell
和可执行
参数
以获取与默认行为的其他差异。除非另有说明,否则建议按照顺序传递参数
。
在Unix上,如果args
是一个字符串,则该字符串将被解释为要执行的程序的名称或路径。但是,只有在不向程序传递参数的情况下才能完成此操作。
注意
shlex.split()
在确定参数
的正确标记时,尤其是在复杂情况下可能有用:
>>> import shlex, subprocess
>>> command_line = raw_input()
/bin/vikings -input eggs.txt -output "spam spam.txt" -cmd "echo '$MONEY'"
>>> args = shlex.split(command_line)
>>> print args
['/bin/vikings', '-input', 'eggs.txt', '-output', 'spam spam.txt', '-cmd', "echo '$MONEY'"]
>>> p = subprocess.Popen(args) # Success!
请特别注意,shell中由空白分隔的选项(例如-input
)和参数(如eggs.txt
)将放在单独的列表元素中,而在shell中使用时需要引用或反斜杠转义的参数(例如包含空格或上面显示的echo
命令的文件名)是单个列表元素。
在Windows上,如果args
是序列,则它将按照在Windows 上将参数
序列转换为字符串中所述的方式转换为字符串。这是因为底层CreateProcess()
在字符串上运行。
所述shell
参数(默认为False
)指定是否使用壳作为要执行的程序。如果shell
是True
,建议将args
作为字符串传递,而不是作为序列传递。
在Unix上shell=True
,shell默认为/bin/sh
。如果args
是一个字符串,则该字符串指定通过shell执行的命令。这意味着该字符串的格式必须与在shell提示符下键入时的格式完全相同。这包括,例如,在其中包含空格的引号或反斜线转义文件名。如果args
是一个序列,则第一项指定命令字符串,并且任何附加项都将被视为shell本身的附加参数。也就是说,Popen
相当于:
Popen(['/bin/sh', '-c', args[0], args[1], ...])
在Windows上shell=True
,COMSPEC
环境变量指定了默认的shell。您需要shell=True
在Windows 上指定的唯一时间是您希望执行的命令内置到shell中(例如dir
或copy
)。您不需要shell=True
运行批处理文件或基于控制台的可执行文件。
警告
shell=True
如果与不可信输入结合使用,传递可能会带来安全隐患。有关详细信息,请参阅常用参数下的警告。
如果给定,bufsize
与内建的open()函数的相应参数具有相同的含义:0
意味着无缓冲,1
意味着行缓冲,任何其他正值意味着使用(近似)该大小的缓冲区。负bufsize
意味着使用系统默认值,通常意味着完全缓冲。bufsize
的默认值是0
(无缓冲)。
注意
如果遇到性能问题,建议您尝试通过将bufsize
设置为-1或足够大的正值(如4096)来启用缓冲。
该可执行文件
参数
指定的替代程序来执行。这是很少需要的。何时shell=False
,可执行文件
会将程序替换为由args
指定的执行程序。但是,原始参数
仍然传递给程序。大多数程序会将由args
指定的程序视为命令名称,这可能与实际执行的程序不同。在Unix上,args
名称成为ps
等实用程序中可执行文件
的显示名称。如果shell=True
在Unix上可执行
参数
指定了默认的替换shell /bin/sh
。
stdin
,stdout
和stderr分别
指定执行的程序的标准输入,标准输出和标准错误文件句柄。有效值是PIPE
一个现有的文件描述符(一个正整数),一个现有的文件对象,和None
。PIPE
表示应该创建一个新的管道给孩子。使用默认设置None
,不会发生重定向; 孩子的文件句柄将从父类继承。此外,stderr
可以是STDOUT
,这表示应该将stderr
数据从子进程捕获到与stdout
相同的文件句柄中。
如果将preexec_fn
设置为可调用对象,则该对象将在子进程执行前被调用。(仅适用于Unix)
如果close_fds
为true,则将执行子进程之前的所有文件描述符0
,1
并且2
将被关闭。(仅适用于Unix)。或者,在Windows上,如果close_fds
为true,那么子进程将不会继承任何句柄。请注意,在Windows上,您不能将close_fds
设置为true,并通过设置stdin
,stdout
或stderr来
重定向标准句柄。
如果cwd
不是None
,那么在执行之前,该子目前的目录将被更改为cwd
。请注意,搜索可执行文件时不考虑此目录,因此您无法指定程序相对于cwd
的路径。
如果env
不是None
,它必须是一个为新进程定义环境变量的映射; 这些用来代替继承当前进程的环境,这是默认行为。
注意
如果指定,env
必须
提供程序执行所需的任何变量。在Windows上,为了运行并行程序集,指定的env
必须
包含有效的SystemRoot
。
如果universal_newlines
是True
,文件对象标准输出
和标准错误
被打开,如文本文件通用换行模式。行可以通过任何'\n'
Unix终止约定,'\r'
旧的Macintosh约定或'\r\n'
Windows约定来终止。所有这些外部表示都被'\n'
Python程序看到。
注意
此功能仅在Python使用通用换行支持(默认)构建时才可用。此外,文件对象的换行符属性stdout
,stdin
并stderr
不会通过communications()方法更新。
如果给出,startupinfo
将是一个STARTUPINFO
对象,它被传递给底层CreateProcess
函数。创造性标志
,如果给出,可以是CREATE_NEW_CONSOLE
或CREATE_NEW_PROCESS_GROUP
。(仅限Windows)
1.3。例外
在新程序开始执行之前,子进程中引发的异常将在父进程中重新提出。另外,异常对象将会有一个额外的属性被调用child_traceback
,这是一个字符串,其中包含来自孩子视角的回溯信息。
最常见的例外是OSError
。例如,尝试执行不存在的文件时会发生这种情况。应用程序应该准备OSError
例外。
ValueError
如果Popen
使用无效参数调用A 将会被提出。
check_call()
如果被调用的进程返回一个非零的返回码,check_output()
将会引发CalledProcessError
。
1.4。安全
与其他一些popen函数不同,此实现不会隐式调用系统shell。这意味着所有字符(包括shell元字符)都可以安全地传递给子进程。显然,如果shell被显式调用,那么应用程序有责任确保所有空白和元字符都被适当引用。
2. Popen对象
Popen
类的实例有以下方法:
Popen.poll()
检查子进程是否已终止。设置并返回returncode
属性。
Popen.wait()
等待子进程终止。设置并返回returncode
属性。
警告
这会在使用stdout=PIPE
和/或stderr=PIPE
和子进程产生足够的输出到管道时发生死锁,从而阻塞等待OS管道缓冲区接受更多数据。使用communicate()
以避免这种情况。
Popen.communicate(input=None)
与流程进行交互:将数据发送到stdin。从stdout和stderr中读取数据,直到达到文件结尾。等待进程终止。可选的输入
参数应该是要发送到子进程的字符串,或者None
如果没有数据应该发送给子进程。
communicate()
returns a tuple (stdoutdata, stderrdata)
.
请注意,如果要将数据发送到进程的stdin,则需要使用创建Popen对象stdin=PIPE
。同样,要获得除None
结果元组以外的任何内容,您需要提供stdout=PIPE
和/或stderr=PIPE
也可以。
注意
读取的数据缓冲在内存中,所以如果数据量很大或无限,就不要使用这种方法。
Popen.send_signal(signal)
将信号发送
给子类。
注意
在Windows上,SIGTERM是别名terminate()
。可以将CTRL_C_EVENT和CTRL_BREAK_EVENT发送到以包含的creationflags
参数开始的进程CREATE_NEW_PROCESS_GROUP
。
2.6版本中的新功能。
Popen.terminate()
停止子类。在Posix操作系统上,该方法向孩子发送SIGTERM。在Windows上调用Win32 API函数TerminateProcess()
来停止该子项。
2.6版本中的新功能。
Popen.kill()
停止子类。在Posix操作系统上,该函数向孩子发送SIGKILL。在Windows上kill()
是别名terminate()
。
2.6版本中的新功能。
以下属性也可用:
警告
使用communicate()
而不是.stdin.write
,.stdout.read
或.stderr.read
避免死锁由于任何其他操作系统管缓冲区填满并阻塞子进程。
Popen.stdin
如果stdin
参数是PIPE
,则该属性是为子进程提供输入的文件对象。否则,它是None
。
Popen.stdout
如果stdout
参数是PIPE
,则此属性是提供子进程输出的文件对象。否则,它是None
。
Popen.stderr
如果stderr
参数是PIPE
,则此属性是一个文件对象,它提供子进程的错误输出。否则,它是None
。
Popen.pid
子进程的进程ID。
请注意,如果将shell
参数设置为True
,则这是生成的shell
的进程ID。
Popen.returncode
子类返回代码,由poll()
和wait()
(和间接地communicate()
)设置。一个None
值表示进程尚未结束。
负值-N
表示该孩子被信号终止N
(仅限Unix)。
3. Windows Popen助手
该STARTUPINFO
级和以下常量仅适用于Windows。
class subprocess.STARTUPINFO
部分支持Windows STARTUPINFO(https://msdn.microsoft.com/en-us/library/ms686331(v = vs.85%29.aspx)结构用于Popen
创建。
dwFlags
一个位域,用于确定STARTUPINFO
进程创建窗口时是否使用某些属性。
si = subprocess.STARTUPINFO()
si.dwFlags = subprocess.STARTF_USESTDHANDLES | subprocess.STARTF_USESHOWWINDOW
hStdInput
如果dwFlags
指定STARTF_USESTDHANDLES
,则此属性是该进程的标准输入句柄。如果STARTF_USESTDHANDLES
未指定,则标准输入的默认值是键盘缓冲区。
hStdOutput
如果dwFlags
指定STARTF_USESTDHANDLES
,则此属性是该进程的标准输出句柄。否则,该属性将被忽略,标准输出的默认值是控制台窗口的缓冲区。
hStdError
如果dwFlags
指定STARTF_USESTDHANDLES
,则此属性是该进程的标准错误句柄。否则,该属性将被忽略,标准错误的默认值是控制台窗口的缓冲区。
wShowWindow
如果dwFlags
指定STARTF_USESHOWWINDOW
,则此属性可以是可以nCmdShow
在ShowWindow 的参数中指定的任何值(https://msdn.microsoft.com/zh-cn/library/ms633548(v = vs.85%29.aspx)函数,除了SW_SHOWDEFAULT
。否则,该属性将被忽略。
SW_HIDE
为此属性提供。它在Popen
被调用时使用shell=True
。
3.1。常量
该subprocess
模块暴露下列常量。
subprocess.STD_INPUT_HANDLE
标准输入设备。最初,这是控制台输入缓冲区,CONIN$
。
subprocess.STD_OUTPUT_HANDLE
标准输出设备。最初,这是活动控制台屏幕缓冲区,CONOUT$
。
subprocess.STD_ERROR_HANDLE
标准的错误设备。最初,这是活动控制台屏幕缓冲区,CONOUT$
。
subprocess.SW_HIDE
隐藏窗口。另一个窗口将被激活。
subprocess.STARTF_USESTDHANDLES
指定STARTUPINFO.hStdInput
,STARTUPINFO.hStdOutput
和STARTUPINFO.hStdError
属性包含的附加信息。
subprocess.STARTF_USESHOWWINDOW
指定该STARTUPINFO.wShowWindow
属性包含附加信息。
subprocess.CREATE_NEW_CONSOLE
新进程有一个新的控制台,而不是继承其父控制台(默认)。
该标志始终在Popen
创建时设置shell=True
。
subprocess.CREATE_NEW_PROCESS_GROUP
一个Popen
creationflags
参数指定一个新的进程组将被创建。该标志对于os.kill()
在子进程上使用是必需的。
如果CREATE_NEW_CONSOLE
被指定,该标志被忽略。
4.用子流程模块替换旧功能
在本节中,“a变成b”表示b可以用作a的替换。
注意
如果执行的程序无法找到,本节中的所有“a”功能都将无效(或多或少); OSError
代替“b” 代替。
另外,如果请求的操作产生非零返回码,则替换使用check_output()
将失败CalledProcessError
。输出仍然可用作output
引发异常的属性。
在以下示例中,我们假设相关功能已从subprocess
模块导入。
4.1。替换/ bin / sh外壳反引号
output=`mycmd myarg`
变为:
output = check_output(["mycmd", "myarg"])
4.2。更换壳管道
output=`dmesg | grep hda`
变为:
p1 = Popen(["dmesg"], stdout=PIPE)
p2 = Popen(["grep", "hda"], stdin=p1.stdout, stdout=PIPE)
p1.stdout.close() # Allow p1 to receive a SIGPIPE if p2 exits.
output = p2.communicate()[0]
启动p2后,p1.stdout.close()调用非常重要,以便p1在p1之前退出时接收SIGPIPE。
或者,对于可信输入,shell自己的管线支持仍可以直接使用:
output=`dmesg | grep hda`
变为:
output=check_output("dmesg | grep hda", shell=True)
4.3。更换os.system()
status = os.system("mycmd" + " myarg")
# becomes
status = subprocess.call("mycmd" + " myarg", shell=True)
笔记:
- 通过shell调用程序通常是不需要的。一个更现实的例子如下:try:retcode = call(“mycmd”+“myarg”,shell = True)如果retcode <0:print >> sys.stderr, “孩子被信号终止”,-retcode else:print >> sys.stderr,“孩子返回”,除OSError之外的编码为e:print >> sys.stderr,“执行失败:”,e4.4。替换os.spawnfamilyP_NOWAIT例如:PID = os.spawnlp(os.P_NOWAIT, “/斌/ mycmd”, “mycmd”, “myarg”)==> PID = POPEN([ “/ bin中/ mycmd”, “myarg”])pidP_WAIT例如:retcode = os.spawnlp(os.P_WAIT,“/ bin / mycmd”,“mycmd”,“myarg”)==> retcode = call([“/ bin / mycmd”,“myarg”])例子: os.spawnlp(os.P_NOWAIT,path,args)==> Popen([path] + args [1:])环境示例:os.spawnlpe(os.P_NOWAIT,“/ bin / mycmd”,“mycmd”,“ myarg“,env)==> Popen([”/ bin / mycmd“,”myarg“],env = {”PATH“:”/usr/bin"})4.5。更换os.popen(),os.popen2(),os.popen3()rc = pipe.close()如果rc不是None且rc >> 8:print“有一些错误”==> process = Popen(“cmd”,shell = True,stdin = PIPE)... process .stdin.close()if process.wait()!= 0:print“有一些错误”4.6。从中取代功能popen2模块(child_stdout,child_stdin)= popen2.popen2( “somestring”,BUFSIZE,模式)==> P = POPEN( “somestring”,壳=真,BUFSIZE = BUFSIZE,标准输入= PIPE,由于输出= PIPE,close_fds =真) (child_stdout,child_stdin)=(p.stdout,p.stdin)在Unix上,popen2也接受一个序列作为执行命令,在这种情况下,参数将直接传递给程序,而不需要shell干预。这个用法可以替换为:(child_stdout,child_stdin)= popen2.popen2([“mycmd”,“myarg”],bufsize,mode)==> p = Popen([“mycmd”,“myarg”],bufsize = BUFSIZE,标准输入= PIPE,由于输出= PIPE,close_fds =真)(child_stdout,child_stdin)=(p.stdout,p.stdin)popen2.Popen3和popen2.Popen4基本上如工作subprocess.Popen,不同之处在于:
Popen
如果执行失败会引发异常。
- 该
capturestderr
参数被替换为标准错误
的说法。
stdin=PIPE
并且stdout=PIPE
必须指定。
- 默认情况下,popen2关闭所有文件描述符,但必须
close_fds=True
使用Popen
。
5.注意
5.1。在Windows上将参数序列转换为字符串
在Windows上,参数
序列被转换为可以使用以下规则解析的字符串(它对应于MS C运行时使用的规则):
- 参数是由空白分隔的,它是一个空格或一个制表符。
- 无论内部包含空格,用双引号括起来的字符串都被解释为单个参数。引用的字符串可以嵌入参数中。
- 前面加一个反斜杠的双引号被解释为文字双引号。
- 反斜杠从字面上解释,除非它们立即在双引号之前。
- 如果反斜杠立即在双引号之前,则每对反斜杠都将被解释为文字反斜杠。如果反斜杠的数量是奇数,则最后一个反斜杠将转义下一个双引号,如规则3所述。