subprocess ---子流程管理

源代码: Lib/subprocess.py


这个 subprocess 模块允许您生成新进程,连接到它们的输入/输出/错误管道,并获取它们的返回代码。此模块打算替换几个旧的模块和功能:

os.system
os.spawn*

关于如何 subprocess 模块可用于更换这些模块,功能见以下章节。

参见

PEP 324 --提出子流程模块的PEP

使用 subprocess 模块

调用子流程的建议方法是使用 run() 它可以处理的所有用例的函数。对于更高级的用例,底层 Popen 接口可以直接使用。

这个 run() 在python 3.5中添加了函数;如果需要保持与旧版本的兼容性,请参见 旧的高级API 部分。

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, **other_popen_kwargs)

运行以下描述的命令 args . 等待命令完成,然后返回 CompletedProcess 实例。

上面显示的参数只是最常见的参数,如下所述 常用参数 (因此,在缩写签名中只使用关键字表示法)。完整函数签名与 Popen 构造函数-此函数的大部分参数都传递给该接口。( timeoutinput检查capture_output 不是。)

如果 capture_output 为真,将捕获stdout和stderr。使用时,内部 Popen 对象是用自动创建的 stdout=PIPEstderr=PIPE . 这个 标准输出标准错误 不能同时提供参数 capture_output . 如果您希望捕获并将两个流合并为一个流,请使用 stdout=PIPEstderr=STDOUT 而不是 capture_output .

这个 timeout 参数传递给 Popen.communicate() . 如果超时过期,子进程将被终止并等待。这个 TimeoutExpired 子进程终止后将重新引发异常。

这个 input 参数传递给 Popen.communicate() 这样子进程的stdin。如果使用,它必须是字节序列,或者是字符串,如果 encodingerrors 指定或 text 是真的。使用时,内部 Popen 对象是用自动创建的 stdin=PIPE*stdin*参数也不能使用。

如果 检查 为真,进程以非零退出代码退出,a CalledProcessError 将引发异常。该异常的属性包含参数、退出代码、stdout和stderr(如果捕获了它们)。

如果 encodingerrors 已指定,或 text 如果为true,则在文本模式下使用指定的 encodingerrorsio.TextIOWrapper 违约。这个 universal_newlines 参数等价于 text 并提供向后兼容性。默认情况下,文件对象以二进制模式打开。

如果 env 不是 None ,它必须是定义新进程的环境变量的映射;使用这些变量,而不是继承当前进程的环境的默认行为。直接传给 Popen .

实例:

>>> subprocess.run(["ls", "-l"])  # doesn't capture output
CompletedProcess(args=['ls', '-l'], returncode=0)

>>> subprocess.run("exit 1", shell=True, check=True)
Traceback (most recent call last):
  ...
subprocess.CalledProcessError: Command 'exit 1' returned non-zero exit status 1

>>> subprocess.run(["ls", "-l", "/dev/null"], capture_output=True)
CompletedProcess(args=['ls', '-l', '/dev/null'], returncode=0,
stdout=b'crw-rw-rw- 1 root root 1, 3 Jan 23 16:23 /dev/null\n', stderr=b'')

3.5 新版功能.

在 3.6 版更改: 补充 encodingerrors 参数

在 3.7 版更改: 增加了 text 参数,作为更易于理解的 universal_newlines . 增加了 capture_output 参数。

class subprocess.CompletedProcess

返回值来自 run() ,表示已完成的进程。

args

用于启动进程的参数。这可能是一个列表或字符串。

returncode

子进程的退出状态。通常,退出状态为0表示它已成功运行。

负值 -N 指示子级已被信号终止 N (仅限POSIX)。

stdout

从子进程捕获stdout。字节序列或字符串,如果 run() 调用时使用了编码、错误或文本=true。 None 如果未捕获stdout。

如果您使用 stderr=subprocess.STDOUT ,stdout和stderr将在此属性中组合,并且 stderrNone .

stderr

已从子进程捕获stderr。字节序列或字符串,如果 run() 调用时使用了编码、错误或文本=true。 None 如果未捕获stderr。

check_returncode()

如果 returncode 非零,提高 CalledProcessError .

3.5 新版功能.

subprocess.DEVNULL

可以用作 stdinstdoutstderr 参数 Popen 并指示特殊文件 os.devnull 将被使用。

3.3 新版功能.

subprocess.PIPE

可以用作 stdinstdoutstderr 参数 Popen 并指示应打开通向标准流的管道。最有用的 Popen.communicate() .

subprocess.STDOUT

可以用作 stderr 参数 Popen 并指出标准错误应该和标准输出进入同一个句柄。

exception subprocess.SubprocessError

此模块中所有其他异常的基类。

3.3 新版功能.

exception subprocess.TimeoutExpired

的子类 SubprocessError ,在等待子进程时超时过期时引发。

cmd

用于生成子进程的命令。

timeout

超时(秒)。

output

如果子进程被 run()check_output() . 否则, None .

stdout

输出别名,用于对称 stderr .

stderr

子进程的stderr输出(如果被捕获) run() . 否则, None .

3.3 新版功能.

在 3.5 版更改: stdoutstderr 添加的属性

exception subprocess.CalledProcessError

的子类 SubprocessError ,由运行进程时引发 check_call()check_output() 返回非零退出状态。

returncode

子进程的退出状态。如果进程因信号而退出,这将是负信号号。

cmd

用于生成子进程的命令。

output

如果子进程被 run()check_output() . 否则, None .

stdout

输出别名,用于对称 stderr .

stderr

子进程的stderr输出(如果被捕获) run() . 否则, None .

在 3.5 版更改: stdoutstderr 添加的属性

常用参数

为了支持各种各样的用例, Popen 构造函数(和方便函数)接受大量可选参数。对于大多数典型的用例,这些参数中的许多都可以安全地保留为默认值。最常用的参数是:

args 对于所有调用都是必需的,并且应该是字符串或程序参数序列。通常首选提供一系列参数,因为它允许模块处理任何所需的参数转义和引用(例如允许文件名中有空格)。如果传递单个字符串,则 必须是 True (见下文)或者字符串必须简单地命名要执行的程序,而不指定任何参数。

stdinstdoutstderr 分别指定执行程序的标准输入、标准输出和标准错误文件句柄。有效值为 PIPEDEVNULL ,现有文件描述符(正整数)、现有文件对象,以及 None . PIPE 指示应创建到子管道的新管道。 DEVNULL 指示特殊文件 os.devnull 将被使用。默认设置为 None ,不会发生重定向;子级的文件句柄将从父级继承。此外, stderr 可以是 STDOUT ,表示子进程中的stderr数据应捕获到与的相同的文件句柄中。 stdout .

如果 encodingerrors 已指定,或 text (也称为 universal_newlines )是真的,文件对象 stdinstdoutstderr 将在文本模式下使用 encodingerrors 在调用或的默认值中指定 io.TextIOWrapper .

为了 stdin,行尾字符 '\n' 将在输入中转换为默认的行分隔符 os.linesep . 为了 stdoutstderr ,输出中的所有行尾都将转换为 '\n' . 有关更多信息,请参阅 io.TextIOWrapper 类时 newline 其构造函数的参数为 None .

如果不使用文本模式, stdinstdoutstderr 将作为二进制流打开。不执行编码或行尾转换。

3.6 新版功能: 补充 encodingerrors 参数。

3.7 新版功能: 增加了 text 参数作为的别名 universal_newlines .

注解

文件对象的newlines属性 Popen.stdinPopen.stdoutPopen.stderr 不由更新 Popen.communicate() 方法。

如果 True ,指定的命令将通过shell执行。如果您主要将python用于它在大多数系统shell上提供的增强控制流,并且仍然希望方便地访问其他shell功能,如shell管道、文件名通配符、环境变量扩展和扩展 ~ 到用户的主目录。但是,请注意,python本身提供了许多类似shell的特性的实现(特别是, globfnmatchos.walk()os.path.expandvars()os.path.expanduser()shutil

在 3.3 版更改: 什么时候? universal_newlinesTrue ,类使用编码 locale.getpreferredencoding(False) 而不是 locale.getpreferredencoding() . 见 io.TextIOWrapper 类以获取有关此更改的详细信息。

注解

阅读 Security Considerations 使用前分区 shell=True .

这些选项以及所有其他选项在 Popen 建造商文件。

Popen构造函数

此模块中的基础流程创建和管理由 Popen 类。它提供了很大的灵活性,使开发人员能够处理便利功能中没有涉及的不太常见的情况。

class 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=(), *, group=None, extra_groups=None, user=None, umask=- 1, encoding=None, errors=None, text=None, pipesize=- 1)

在新进程中执行子程序。在POSIX上,该类使用 os.execvpe() -执行子程序的类似行为。在Windows上,该类使用Windows CreateProcess() 功能。的参数 Popen 如下所示。

args 应该是程序参数序列,或者是单个字符串,或者 path-like object . 默认情况下,要执行的程序是 args 如果 args 是一个序列。如果 args 是一个字符串,解释依赖于平台,如下所述。见 可执行文件 其他不同于默认行为的参数。除非另有说明,建议通过 args 作为一个序列。

警告

为了获得最大的可靠性,请使用可执行文件的完全限定路径。要在上搜索非限定名称,请执行以下操作 PATH ,使用 shutil.which() 。在所有平台上,通过 sys.executable 是再次启动当前Python解释器的推荐方式,并使用 -m 用于启动已安装模块的命令行格式。

解决以下问题的路径 可执行文件 (或第一项 args )取决于平台。有关POSIX,请参见 os.execvpe() ,并注意在解析或搜索可执行路径时, cwd 重写当前工作目录,并 env 可以重写 PATH 环境变量。对于Windows,请参阅 lpApplicationNamelpCommandLine WinAPI的参数 CreateProcess ,并请注意,使用解析或搜索可执行路径时 shell=Falsecwd 不会重写当前工作目录,并且 env 不能重写 PATH 环境变量。使用完整路径可以避免所有这些变化。

将一些参数作为序列传递给外部程序的示例如下:

Popen(["/usr/bin/git", "commit", "-m", "Fixes a bug."])

关于POSIX,如果 args 是一个字符串,该字符串被解释为要执行的程序的名称或路径。但是,这只能在不向程序传递参数的情况下完成。

注解

如何将shell命令分解为一系列参数可能并不明显,特别是在复杂的情况下。 shlex.split() 可以说明如何确定 args ::

>>> import shlex, subprocess
>>> command_line = 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!

特别要注意选项(例如 -input )和参数(如 eggs.txt )在shell中由空白分隔的参数放入单独的列表元素中,而在shell中使用时需要引用或反斜杠转义的参数(例如包含空格或 echo 上面显示的命令)是单个列表元素。

在Windows上,如果 args 是一个序列,它将以中描述的方式转换为字符串。 在Windows上将参数序列转换为字符串 .这是因为 CreateProcess() 对字符串进行操作。

在 3.6 版更改: args 参数接受 path-like object 如果 False 以及一个序列,其中包含POSIX上类似路径的对象。

在 3.8 版更改: args 参数接受 path-like object 如果 False 以及包含字节和类似路径的对象的序列。

这个 参数(默认为 False )指定是否将shell用作要执行的程序。如果 True ,建议通过 args 作为字符串而不是序列。

在posix上 shell=True ,shell默认为 /bin/sh . 如果 args 是一个字符串,该字符串指定要通过shell执行的命令。这意味着字符串的格式必须与在shell提示下键入时的格式完全相同。例如,这包括用空格引用或反斜杠转义文件名。如果 args 是一个序列,第一个项指定命令字符串,任何附加项都将被视为shell本身的附加参数。这就是说, Popen 等同于:

Popen(['/bin/sh', '-c', args[0], args[1], ...])

在Windows上 shell=True , the COMSPEC 环境变量指定默认shell。唯一需要指定的时间 shell=True 在Windows上,是将要执行的命令内置到shell(例如 dircopy )你不需要 shell=True 运行批处理文件或基于控制台的可执行文件。

注解

阅读 Security Considerations 使用前分区 shell=True .

蟾蜍尺码 将作为相应的参数提供给 open() 函数在创建stdin/stdout/stderr管道文件对象时:

  • 0 表示无缓冲(读写是一个系统调用,可以短时间返回)

  • 1 表示线路缓冲(仅在以下情况下可用 universal_newlines=True 即,在文本模式下)

  • 任何其他正值意味着使用大约该大小的缓冲区

  • 负bufsize(默认值)表示系统默认值为io。将使用默认缓冲区大小。

在 3.3.1 版更改: 蟾蜍尺码 现在默认为-1,默认情况下启用缓冲以匹配大多数代码期望的行为。在python 3.2.4和3.3.1之前的版本中,它错误地默认为 0 它没有缓冲,允许短读。这是无意的,与大多数代码预期的python 2行为不匹配。

这个 可执行文件 参数指定要执行的替换程序。这是很少需要的。什么时候? shell=False可执行文件 替换由指定的要执行的程序 args . 但是,原版 args 仍传递给程序。大多数程序处理由指定的程序 args 作为命令名,它可以不同于实际执行的程序。在POSIX上, args 名称将成为实用程序中可执行文件的显示名称,例如 ps . 如果 shell=True ,在POSIX上 可执行文件 参数为默认值指定替换外壳程序 /bin/sh .

在 3.6 版更改: 可执行文件 参数接受 path-like object 在POSIX上。

在 3.8 版更改: 可执行文件 参数接受字节和 path-like object 在Windows上。

stdinstdoutstderr 分别指定执行程序的标准输入、标准输出和标准错误文件句柄。有效值为 PIPEDEVNULL ,现有的文件描述符(正整数),现有的 file objectNone . PIPE 指示应创建到子管道的新管道。 DEVNULL 指示特殊文件 os.devnull 将被使用。默认设置为 None ,不会发生重定向;子级的文件句柄将从父级继承。此外, stderr 可以是 STDOUT 指示应用程序中的stderr数据应捕获到与stdout相同的文件句柄中。

如果 preexec_fn 设置为可调用对象,将在执行子进程之前在子进程中调用此对象。(仅限POSIX)

警告

这个 preexec_fn 在应用程序中存在线程时使用参数是不安全的。子进程可能在调用exec之前死锁。如果你必须使用它,那就保持它的微不足道!最小化调用的库数。

注解

如果您需要为子项修改环境,请使用 env 参数而不是在 preexec_fn . 这个 start_new_session 参数可以取代以前常用的 preexec_fn 调用子级中的os.setsid()。

在 3.8 版更改: 这个 preexec_fn 子解释器不再支持参数。在子解释器中使用参数会引发 RuntimeError . 新的限制可能会影响部署在mod_wsgi、uWSGI和其他嵌入式环境中的应用程序。

如果 close_fds 为真,除 012 将在执行子进程之前关闭。否则当 close_fds 为假,文件描述符遵守其可继承标志,如中所述。 文件描述符的继承 .

在Windows上,如果 close_fds 如果为true,则除非在 handle_list 元素 STARTUPINFO.lpAttributeList 或通过标准句柄重定向。

在 3.2 版更改: 默认值为 close_fds 已从更改 False 到上面描述的。

在 3.7 版更改: 在Windows上 close_fds 已从更改 FalseTrue 重定向标准句柄时。现在可以设置 close_fdsTrue 重定向标准句柄时。

pass_fds 是一个可选的文件描述符序列,用于在父级和子级之间保持打开状态。提供任何 pass_fds 军队 close_fds 成为 True . (仅限POSIX)

在 3.2 版更改: 这个 pass_fds 已添加参数。

如果 cwd 不是 None 时,该函数将工作目录更改为 cwd 在处决孩子之前。 cwd 可以是字符串、字节或 path-like 对象。在POSIX中,该函数查找 可执行文件 (或中的第一个项目 args )相对于 cwd 如果可执行路径是相对路径。

在 3.6 版更改: cwd 参数接受 path-like object 在POSIX上。

在 3.7 版更改: cwd 参数接受 path-like object 在Windows上。

在 3.8 版更改: cwd 参数接受Windows上的bytes对象。

如果 restore_signals 为真(默认值),python设置为sig_ign的所有信号都将在exec之前的子进程中还原为sig_dfl。目前这包括sigpipe、sigxfz和sigxfsz信号。(仅限POSIX)

在 3.2 版更改: restore_signals 加入。

如果 start_new_session 如果为true,则在执行子进程之前,将在子进程中进行setsid()系统调用。(仅限POSIX)

在 3.2 版更改: start_new_session 加入。

如果 不是 None ,在执行子进程之前,将在子进程中进行setregid()系统调用。如果提供的值是字符串,则将通过 grp.getgrnam() 以及 gr_gid 将被使用。如果该值是整数,则将逐字传递。(仅限POSIX)

Availability :POSIX公司

3.9 新版功能.

如果 extra_groups 不是 None ,在执行子进程之前,将在子进程中进行setgroups()系统调用。提供的字符串 extra_groups 将通过 grp.getgrnam() 以及 gr_gid 将被使用。整数值将逐字传递。(仅限POSIX)

Availability :POSIX公司

3.9 新版功能.

如果 user 不是 None ,在执行子进程之前,将在子进程中进行setreuid()系统调用。如果提供的值是字符串,则将通过 pwd.getpwnam() 以及 pw_uid 将被使用。如果该值是整数,则将逐字传递。(仅限POSIX)

Availability :POSIX公司

3.9 新版功能.

如果 乌马斯克 不是负的,在执行子进程之前,将在子进程中进行umask()系统调用。

Availability :POSIX公司

3.9 新版功能.

如果 env 不是 None ,它必须是定义新进程的环境变量的映射;使用这些变量,而不是继承当前进程的环境的默认行为。

注解

如果有规定, env 必须提供程序执行所需的任何变量。在Windows上,为了运行 side-by-side assembly 指定的 env must 包括有效 SystemRoot .

如果 encodingerrors 已指定,或 text 是真的,文件对象 stdinstdoutstderr 在文本模式下以指定的编码打开,并且 errors ,如上所述 常用参数 . 这个 universal_newlines 参数等价于 text 并提供向后兼容性。默认情况下,文件对象以二进制模式打开。

3.6 新版功能: encodingerrors 加入。

3.7 新版功能: text 添加为更可读的别名 universal_newlines .

如果给出的话, 启动信息 将是 STARTUPINFO 对象,传递给基础 CreateProcess 功能。 创建标志 如果给定,则可以是以下一个或多个标志:

管径 可用于在以下情况下更改管道的大小 PIPE 用于 标准标准输出标准错误 。管道的大小仅在支持此功能的平台上更改(撰写本文时仅更改Linux)。其他平台将忽略此参数。

3.10 新版功能: 这个 pipesize 参数已添加。

popen对象通过 with 语句:退出时,关闭标准文件描述符,并等待进程。::

with Popen(["ifconfig"], stdout=PIPE) as proc:
    log.write(proc.stdout.read())

提出一个 auditing event subprocess.Popen 带着论据 executableargscwdenv .

在 3.2 版更改: 添加了上下文管理器支持。

在 3.6 版更改: popen析构函数现在发出 ResourceWarning 如果子进程仍在运行,则发出警告。

在 3.8 版更改: 波本可以用 os.posix_spawn() 在某些情况下,为了获得更好的性能。在用于Linux和QEMU用户仿真的Windows子系统上,popen构造函数使用 os.posix_spawn() 不再对缺少程序等错误引发异常,但子进程以非零失败 returncode .

例外情况

在新程序开始执行之前,子进程中引发的异常将在父进程中重新引发。

引发的最常见异常是 OSError . 例如,当尝试执行不存在的文件时,就会发生这种情况。应用程序应为 OSError 例外情况。

A ValueError 如果 Popen 用无效参数调用。

check_call()check_output() 将提高 CalledProcessError 如果被调用的进程返回非零返回代码。

所有接受 timeout 参数,例如 call()Popen.communicate() 将提高 TimeoutExpired 如果超时在进程退出之前过期。

此模块中定义的异常都继承自 SubprocessError .

3.3 新版功能: 这个 SubprocessError 已添加基类。

安全注意事项

与其他一些POPEN函数不同,此实现永远不会隐式调用系统外壳。这意味着所有字符,包括外壳元字符,都可以安全地传递给子进程。如果显式调用shell,则通过 shell=True ,则由应用程序负责确保所有空格和元字符都用适当的引号引起来,以避免 shell injection 漏洞。在……上面 some platforms ,则可以使用 shlex.quote() 为这次越狱负责。

Popen对象

的实例 Popen 类具有以下方法:

Popen.poll()

检查子进程是否已终止。设置和返回 returncode 属性。否则,返回 None .

Popen.wait(timeout=None)

等待子进程终止。设置和返回 returncode 属性。

如果进程在 timeout 秒,提高 TimeoutExpired 例外。捕获此异常并重试等待是安全的。

注解

使用时会死锁 stdout=PIPEstderr=PIPE 子进程生成足够的输出到管道,从而阻止等待OS管道缓冲区接受更多数据。使用 Popen.communicate() 当使用管道来避免这种情况时。

注解

该函数使用一个繁忙的循环(非阻塞调用和短睡眠)来实现。使用 asyncio 异步等待模块:请参见 asyncio.create_subprocess_exec .

在 3.3 版更改: timeout 加入。

Popen.communicate(input=None, timeout=None)

与进程交互:将数据发送到stdin。从stdout和stderr读取数据,直到到达文件末尾。等待进程终止并设置 returncode 属性。可选的 输入 参数应该是要发送到子进程的数据,或者 None ,如果不应向子级发送数据。如果以文本模式打开流, 输入 必须是字符串。否则,它必须是字节。

communicate() 返回元组 (stdout_data, stderr_data) .如果以文本模式打开流,则数据将为字符串;否则,为字节。

请注意,如果要将数据发送到进程的stdin,则需要使用 stdin=PIPE . 同样地,除了 None 在结果元组中,您需要 stdout=PIPE 和/或 stderr=PIPE 也是。

如果进程在 timeout 秒,A TimeoutExpired 将引发异常。捕获此异常并重试通信不会丢失任何输出。

如果超时过期,子进程不会被终止,因此为了正确地清理行为良好的应用程序,应该终止子进程并完成通信::

proc = subprocess.Popen(...)
try:
    outs, errs = proc.communicate(timeout=15)
except TimeoutExpired:
    proc.kill()
    outs, errs = proc.communicate()

注解

数据读取是在内存中进行缓冲的,因此如果数据大小很大或不受限制,则不要使用此方法。

在 3.3 版更改: timeout 加入。

Popen.send_signal(signal)

发送信号 信号 给子项。

如果进程完成,则不执行任何操作。

注解

在Windows上,sigterm是的别名 terminate() . ctrl_c_事件和ctrl_break_事件可以发送到用 创建标志 参数,包括 CREATE_NEW_PROCESS_GROUP .

Popen.terminate()

阻止孩子。在POSIX OSs上,该方法将SIGTERM发送给子级。在Windows上Win32 API函数 TerminateProcess() 是为了阻止孩子。

Popen.kill()

杀了孩子。在POSIX操作系统上,函数将SIGKILL发送给子对象。在Windows上 kill() 是一个别名 terminate() .

以下属性也可用:

Popen.args

这个 args 传递给的参数 Popen --程序参数序列或单个字符串。

3.3 新版功能.

Popen.stdin

如果 stdin*参数是 :data:`PIPE` ,此属性是由返回的可写流对象 :func:`open` . 如果 *encodingerrors 指定了参数或 universal_newlines 参数是 True ,流是文本流,否则它是字节流。如果 *stdin*参数不是 PIPE ,此属性是 None .

Popen.stdout

如果 stdout 参数是 PIPE ,此属性是由返回的可读流对象 open() . 从流中读取提供子进程的输出。如果 encodingerrors 指定了参数或 universal_newlines 参数是 True ,流是文本流,否则它是字节流。如果 stdout 参数不是 PIPE ,此属性是 None .

Popen.stderr

如果 stderr 参数是 PIPE ,此属性是由返回的可读流对象 open() . 从流中读取提供子进程的错误输出。如果 encodingerrors 指定了参数或 universal_newlines 参数是 True ,流是文本流,否则它是字节流。如果 stderr 参数不是 PIPE ,此属性是 None .

警告

使用 communicate() 而不是 .stdin.write.stdout.read.stderr.read 以避免由于任何其他OS管道缓冲区填充和阻塞子进程而导致死锁。

Popen.pid

子进程的进程ID。

请注意,如果设置 参数 True ,这是生成的shell的进程ID。

Popen.returncode

子返回代码,由设置 poll()wait() (间接地 communicate() )一 None 值表示进程尚未终止。

负值 -N 指示子级已被信号终止 N (仅限POSIX)。

Windows Popen帮助程序

这个 STARTUPINFO 类和以下常量仅在Windows上可用。

class subprocess.STARTUPINFO(*, dwFlags=0, hStdInput=None, hStdOutput=None, hStdError=None, wShowWindow=0, lpAttributeList=None)

Windows部分支撑 STARTUPINFO _结构用于 Popen 创造。通过将以下属性作为仅关键字参数传递,可以设置这些属性。

在 3.7 版更改: 添加了只支持关键字的参数。

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 _功能,除了 SW_SHOWDEFAULT . 否则,将忽略此属性。

SW_HIDE 为该属性提供。使用时 Popen 被调用 shell=True .

lpAttributeList

过程创建的附加属性字典,如 STARTUPINFOEXUpdateProcThreadAttribute _.

支持的属性:

handle_list

将继承的句柄序列。 close_fds 如果非空,则必须为真。

句柄必须临时设置为可由继承 os.set_handle_inheritable() 当传递给 Popen 构造函数,否则 OSError 将引发Windows错误 ERROR_INVALID_PARAMETER (87)。

警告

在多线程进程中,将此功能与对继承所有句柄的其他进程创建函数(如 os.system() .这也适用于标准句柄重定向,它临时创建可继承的句柄。

3.7 新版功能.

Windows常量

这个 subprocess 模块公开以下常量。

subprocess.STD_INPUT_HANDLE

标准输入设备。最初,这是控制台输入缓冲区, CONIN$ .

subprocess.STD_OUTPUT_HANDLE

标准输出设备。最初,这是活动的控制台屏幕缓冲区, CONOUT$ .

subprocess.STD_ERROR_HANDLE

标准错误设备。最初,这是活动的控制台屏幕缓冲区, CONOUT$ .

subprocess.SW_HIDE

隐藏窗口。将激活另一个窗口。

subprocess.STARTF_USESTDHANDLES

指定 STARTUPINFO.hStdInputSTARTUPINFO.hStdOutputSTARTUPINFO.hStdError 属性包含其他信息。

subprocess.STARTF_USESHOWWINDOW

指定 STARTUPINFO.wShowWindow 属性包含其他信息。

subprocess.CREATE_NEW_CONSOLE

新进程有一个新的控制台,而不是继承其父进程的控制台(默认)。

subprocess.CREATE_NEW_PROCESS_GROUP

A Popen creationflags 用于指定将创建新流程组的参数。此标志对于使用 os.kill() 在子进程上。

如果 CREATE_NEW_CONSOLE 指定。

subprocess.ABOVE_NORMAL_PRIORITY_CLASS

A Popen creationflags 参数指定新进程将具有高于平均优先级。

3.7 新版功能.

subprocess.BELOW_NORMAL_PRIORITY_CLASS

A Popen creationflags 参数,指定新进程将具有低于平均优先级。

3.7 新版功能.

subprocess.HIGH_PRIORITY_CLASS

A Popen creationflags 参数指定新进程将具有高优先级。

3.7 新版功能.

subprocess.IDLE_PRIORITY_CLASS

A Popen creationflags 参数指定新进程将具有空闲(最低)优先级。

3.7 新版功能.

subprocess.NORMAL_PRIORITY_CLASS

A Popen creationflags 参数指定新进程将具有正常优先级。(默认)

3.7 新版功能.

subprocess.REALTIME_PRIORITY_CLASS

A Popen creationflags 参数指定新进程将具有实时优先级。您几乎不应该使用实时优先级类,因为这会中断管理鼠标输入、键盘输入和后台磁盘刷新的系统线程。此类适用于直接与硬件“对话”或执行应具有有限中断的简短任务的应用程序。

3.7 新版功能.

subprocess.CREATE_NO_WINDOW

A Popen creationflags 参数指定新进程不会创建窗口。

3.7 新版功能.

subprocess.DETACHED_PROCESS

A Popen creationflags 参数指定新进程不会继承其父进程的控制台。此值不能与Create_New_控制台一起使用。

3.7 新版功能.

subprocess.CREATE_DEFAULT_ERROR_MODE

A Popen creationflags 参数指定新进程不继承调用进程的错误模式。相反,新进程将获得默认的错误模式。此功能对于禁用硬错误运行的多线程shell应用程序特别有用。

3.7 新版功能.

subprocess.CREATE_BREAKAWAY_FROM_JOB

A Popen creationflags 参数指定新进程与任务不关联。

3.7 新版功能.

旧的高级API

在Python3.5之前,这三个函数组成了到子流程的高级API。您现在可以使用 run() 在许多情况下,但是许多现有的代码调用这些函数。

subprocess.call(args, *, stdin=None, stdout=None, stderr=None, shell=False, cwd=None, timeout=None, **other_popen_kwargs)

运行以下描述的命令 args . 等待命令完成,然后返回 returncode 属性。

需要捕获stdout或stderr的代码应使用 run() 取而代之的是:

run(...).returncode

若要抑制stdout或stderr,请提供值 DEVNULL .

上面显示的参数只是一些常见的参数。完整的函数签名与 Popen 构造函数-此函数传递除 timeout 直接通过那个接口。

注解

不要使用 stdout=PIPEstderr=PIPE 使用此功能。如果子进程生成足够的输出到管道以填充OS管道缓冲区,则子进程将阻塞,因为无法读取管道。

在 3.3 版更改: timeout 加入。

subprocess.check_call(args, *, stdin=None, stdout=None, stderr=None, shell=False, cwd=None, timeout=None, **other_popen_kwargs)

带参数运行命令。等待命令完成。如果返回代码为零,则返回,否则引发 CalledProcessError . 这个 CalledProcessError 对象的返回代码将位于 returncode 属性。

需要捕获stdout或stderr的代码应使用 run() 取而代之的是:

run(..., check=True)

若要抑制stdout或stderr,请提供值 DEVNULL .

上面显示的参数只是一些常见的参数。完整的函数签名与 Popen 构造函数-此函数传递除 timeout 直接通过那个接口。

注解

不要使用 stdout=PIPEstderr=PIPE 使用此功能。如果子进程生成足够的输出到管道以填充OS管道缓冲区,则子进程将阻塞,因为无法读取管道。

在 3.3 版更改: timeout 加入。

subprocess.check_output(args, *, stdin=None, stderr=None, shell=False, cwd=None, encoding=None, errors=None, universal_newlines=None, timeout=None, text=None, **other_popen_kwargs)

用参数运行命令并返回其输出。

如果返回代码为非零,则会引发 CalledProcessError . 这个 CalledProcessError 对象的返回代码将位于 returncode 属性和中的任何输出 output 属性。

这相当于:

run(..., check=True, stdout=PIPE).stdout

上面显示的论点只是一些常见的论点。完整的函数签名与的基本相同 run() -大多数参数直接传递到该接口。一个API偏差 run() 行为存在:传递 input=None 的行为将与 input=b'' (或 input='' 取决于其他参数),而不是使用父级的标准输入文件句柄。

默认情况下,此函数将以编码字节的形式返回数据。输出数据的实际编码可能取决于调用的命令,因此通常需要在应用程序级别处理文本解码。

此行为可以通过设置覆盖 textencodingerrorsuniversal_newlinesTrue 如上所述 常用参数run() .

要同时捕获结果中的标准错误,请使用 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'

3.1 新版功能.

在 3.3 版更改: timeout 加入。

在 3.4 版更改: 支持 input 已添加关键字参数。

在 3.6 版更改: encodingerrors 加入。见 run() 有关详细信息。

3.7 新版功能: text 添加为更可读的别名 universal_newlines .

用替换旧函数 subprocess 模块

在本节中,"a becomes b"意味着B可以用作A的替代品。

注解

如果找不到执行的程序,“A”部分中的所有“A”功能都将自动失败(或多或少);“B”替换将引发 OSError 相反。

此外,替换件使用 check_output() 将失败 CalledProcessError 如果请求的操作生成非零返回代码。输出仍可用作 output 引发的异常的属性。

在下面的示例中,我们假设已经从 subprocess 模块。

替代 /bin/sh shell命令替换

output=$(mycmd myarg)

变成::

output = check_output(["mycmd", "myarg"])

更换壳体管路

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]

这个 p1.stdout.close() 如果p2在p1之前退出,那么启动p2之后的调用对于p1接收SIGPIPE非常重要。

或者,对于可信输入,仍然可以直接使用shell自己的管道支持:

output=$(dmesg | grep hda)

变成::

output = check_output("dmesg | grep hda", shell=True)

替代 os.system()

sts = os.system("mycmd" + " myarg")
# becomes
sts = call("mycmd" + " myarg", shell=True)

笔记:

  • 通常不需要通过shell调用程序。

一个更现实的例子如下:

try:
    retcode = call("mycmd" + " myarg", shell=True)
    if retcode < 0:
        print("Child was terminated by signal", -retcode, file=sys.stderr)
    else:
        print("Child returned", retcode, file=sys.stderr)
except OSError as e:
    print("Execution failed:", e, file=sys.stderr)

替换 os.spawn 家庭

现在的例子:

pid = os.spawnlp(os.P_NOWAIT, "/bin/mycmd", "mycmd", "myarg")
==>
pid = Popen(["/bin/mycmd", "myarg"]).pid

等待示例:

retcode = os.spawnlp(os.P_WAIT, "/bin/mycmd", "mycmd", "myarg")
==>
retcode = call(["/bin/mycmd", "myarg"])

矢量示例:

os.spawnvp(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"})

替代 os.popen()os.popen2()os.popen3()

(child_stdin, child_stdout) = os.popen2(cmd, mode, bufsize)
==>
p = Popen(cmd, shell=True, bufsize=bufsize,
          stdin=PIPE, stdout=PIPE, close_fds=True)
(child_stdin, child_stdout) = (p.stdin, p.stdout)
(child_stdin,
 child_stdout,
 child_stderr) = os.popen3(cmd, mode, bufsize)
==>
p = Popen(cmd, shell=True, bufsize=bufsize,
          stdin=PIPE, stdout=PIPE, stderr=PIPE, close_fds=True)
(child_stdin,
 child_stdout,
 child_stderr) = (p.stdin, p.stdout, p.stderr)
(child_stdin, child_stdout_and_stderr) = os.popen4(cmd, mode, bufsize)
==>
p = Popen(cmd, shell=True, bufsize=bufsize,
          stdin=PIPE, stdout=PIPE, stderr=STDOUT, close_fds=True)
(child_stdin, child_stdout_and_stderr) = (p.stdin, p.stdout)

返回代码处理翻译如下:

pipe = os.popen(cmd, 'w')
...
rc = pipe.close()
if rc is not None and rc >> 8:
    print("There were some errors")
==>
process = Popen(cmd, stdin=PIPE)
...
process.stdin.close()
if process.wait() != 0:
    print("There were some errors")

从中替换函数 popen2 模块

注解

如果popen2函数的cmd参数是字符串,则通过/bin/sh执行该命令。如果是列表,则直接执行该命令。

(child_stdout, child_stdin) = popen2.popen2("somestring", bufsize, mode)
==>
p = Popen("somestring", shell=True, bufsize=bufsize,
          stdin=PIPE, stdout=PIPE, close_fds=True)
(child_stdout, child_stdin) = (p.stdout, p.stdin)
(child_stdout, child_stdin) = popen2.popen2(["mycmd", "myarg"], bufsize, mode)
==>
p = Popen(["mycmd", "myarg"], bufsize=bufsize,
          stdin=PIPE, stdout=PIPE, close_fds=True)
(child_stdout, child_stdin) = (p.stdout, p.stdin)

popen2.Popen3popen2.Popen4 基本工作方式 subprocess.Popen ,除了:

  • Popen 如果执行失败,则引发异常。

  • 这个 卡斯特雷斯德尔 参数替换为 stderr 参数。

  • stdin=PIPEstdout=PIPE 必须指定。

  • popen2默认关闭所有文件描述符,但必须指定 close_fds=True 具有 Popen 以保证在所有平台或以前的python版本上都有这种行为。

旧shell调用函数

该模块还提供了2.x中的以下遗留功能 commands 模块。这些操作隐式地调用系统shell,并且上述关于安全性和异常处理一致性的任何保证对这些函数都无效。

subprocess.getstatusoutput(cmd)

返回 (exitcode, output) 执行的 cmd 在一个外壳里。

执行字符串 cmd 在壳中 Popen.check_output() 返回2元组 (exitcode, output) . 使用区域设置编码;请参见 常用参数 了解更多详细信息。

从输出中去除尾随换行符。命令的退出代码可以解释为子进程的返回代码。例子::

>>> subprocess.getstatusoutput('ls /bin/ls')
(0, '/bin/ls')
>>> subprocess.getstatusoutput('cat /bin/junk')
(1, 'cat: /bin/junk: No such file or directory')
>>> subprocess.getstatusoutput('/bin/junk')
(127, 'sh: /bin/junk: not found')
>>> subprocess.getstatusoutput('/bin/kill $$')
(-15, '')

Availability :Posix和Windows。

在 3.3.4 版更改: 已添加Windows支持。

现在,函数返回(exitcode,output)而不是(status,output),就像在Python3.3.3和更早版本中那样。exitcode的值与 returncode .

subprocess.getoutput(cmd)

返回执行的输出(stdout和stderr) cmd 在一个外壳里。

类似于 getstatusoutput() ,但退出代码被忽略,返回值是包含命令输出的字符串。例子::

>>> subprocess.getoutput('ls /bin/ls')
'/bin/ls'

Availability :Posix和Windows。

在 3.3.4 版更改: 已添加Windows支持

笔记

在Windows上将参数序列转换为字符串

在Windows上 args 序列转换为可以使用以下规则(与MS C运行时使用的规则相对应)解析的字符串:

  1. 参数由空格分隔,空格可以是空格,也可以是制表符。

  2. 由双引号包围的字符串被解释为单个参数,而不考虑其中包含的空格。带引号的字符串可以嵌入到参数中。

  3. 反斜杠前面的双引号被解释为文字双引号。

  4. 反斜杠按字面解释,除非它们紧跟在双引号之前。

  5. 如果反斜杠紧跟在双引号之前,则每对反斜杠都被解释为一个字面值反斜杠。如果反斜杠的数目是奇数,则最后一个反斜杠将跳过规则3中描述的下一个双引号。

参见

shlex

提供解析和转义命令行的函数的模块。