子过程¶
源代码: Lib/asyncio/subprocess.py , Lib/asyncio/base_subprocess.py
本节介绍用于创建和管理子流程的高级异步/等待异步API。
以下是Asyncio如何运行shell命令并获得其结果的示例:
import asyncio
async def run(cmd):
proc = await asyncio.create_subprocess_shell(
cmd,
stdout=asyncio.subprocess.PIPE,
stderr=asyncio.subprocess.PIPE)
stdout, stderr = await proc.communicate()
print(f'[{cmd!r} exited with {proc.returncode}]')
if stdout:
print(f'[stdout]\n{stdout.decode()}')
if stderr:
print(f'[stderr]\n{stderr.decode()}')
asyncio.run(run('ls /zzz'))
将打印:
['ls /zzz' exited with 1]
[stderr]
ls: /zzz: No such file or directory
因为所有的Asyncio子流程函数都是异步的,Asyncio提供了许多工具来处理这些函数,所以很容易并行执行和监视多个子流程。修改上述示例以同时运行多个命令确实很简单:
async def main():
await asyncio.gather(
run('ls /zzz'),
run('sleep 1; echo "hello"'))
asyncio.run(main())
也见 Examples 小节。
创建子流程¶
- coroutine asyncio.create_subprocess_exec(program, *args, stdin=None, stdout=None, stderr=None, limit=None, **kwds)¶
创建子流程。
这个 limit 参数设置缓冲区限制
StreamReader
封装纸Process.stdout
和Process.stderr
(如果subprocess.PIPE
传递给 stdout 和 stderr 参数)。返回A
Process
实例。参见以下文件:
loop.subprocess_exec()
其他参数。
- coroutine asyncio.create_subprocess_shell(cmd, stdin=None, stdout=None, stderr=None, limit=None, **kwds)¶
运行 cmd 外壳命令。
这个 limit 参数设置缓冲区限制
StreamReader
封装纸Process.stdout
和Process.stderr
(如果subprocess.PIPE
传递给 stdout 和 stderr 参数)。返回A
Process
实例。参见以下文件:
loop.subprocess_shell()
其他参数。重要
应用程序有责任确保所有空格和特殊字符都被适当地引用,以避免 shell injection 漏洞。这个
shlex.quote()
函数可用于正确转义将用于构造shell命令的字符串中的空白字符和特殊shell字符。
注解
子进程在以下情况下可用于Windows ProactorEventLoop
是使用的。看见 Subprocess Support on Windows 有关详细信息,请参阅。
参见
Asyncio还具有以下功能 low-level 用于子流程的API: loop.subprocess_exec()
, loop.subprocess_shell()
, loop.connect_read_pipe()
, loop.connect_write_pipe()
以及 Subprocess Transports 和 Subprocess Protocols .
常量¶
- asyncio.subprocess.PIPE¶
可以传递给 stdin, stdout 或 stderr 参数。
如果 PIPE 传递给 *stdin*参数
Process.stdin
属性将指向StreamWriter
实例。如果 PIPE 传递给 stdout 或 stderr 参数,
Process.stdout
和Process.stderr
属性将指向StreamReader
实例。
- asyncio.subprocess.STDOUT¶
可以用作 stderr 参数并指示应将标准错误重定向到标准输出。
- asyncio.subprocess.DEVNULL¶
可以用作 stdin, stdout 或 stderr 进程创建函数的参数。表示特殊文件
os.devnull
将用于相应的子进程流。
与子流程交互¶
两个 create_subprocess_exec()
和 create_subprocess_shell()
函数返回 过程 类。 过程 是一个高级封装器,允许与子流程通信并监视其完成情况。
- class asyncio.subprocess.Process¶
封装由
create_subprocess_exec()
和create_subprocess_shell()
功能。此类的设计目的是具有与
subprocess.Popen
但是有一些显著的区别:与popen不同,流程实例没有与
poll()
方法;这个
communicate()
和wait()
方法没有 timeout 参数:使用wait_for()
功能;这个
Process.wait()
方法是异步的,而subprocess.Popen.wait()
方法被实现为一个阻塞忙环;这个 universal_newlines 不支持参数。
这个类是 not thread safe .
也见 Subprocess and Threads 部分。
- coroutine wait()¶
等待子进程终止。
设置并返回
returncode
属性。注解
此方法在使用时可能死锁
stdout=PIPE
或stderr=PIPE
子进程生成的输出太多,以至于它会阻止等待OS管道缓冲区接受更多数据。使用communicate()
方法在使用管道时避免这种情况。
- coroutine communicate(input=None)¶
与流程交互:
发送数据到 stdin*(如果 *input 不是
None
;从中读取数据 stdout 和 stderr ,直到达到EOF;
等待进程终止。
可选的 input 参数是数据 (
bytes
对象)将发送到子进程。返回元组
(stdout_data, stderr_data)
.如果任一
BrokenPipeError
或ConnectionResetError
写入时引发异常 input 进入之内 stdin,忽略异常。当进程在所有数据写入之前退出时,就会出现这种情况。 stdin.如果需要将数据发送到进程' stdin,需要使用创建流程
stdin=PIPE
. 同样地,除了None
在结果元组中,必须使用stdout=PIPE
和/或stderr=PIPE
参数。注意,数据读取是在内存中进行缓冲的,因此如果数据大小很大或不受限制,则不要使用此方法。
- send_signal(signal)¶
发送信号 信号 到子进程。
注解
在Windows上,
SIGTERM
是一个别名terminate()
.CTRL_C_EVENT
和CTRL_BREAK_EVENT
可以发送到以 创建标志 参数,包括CREATE_NEW_PROCESS_GROUP
.
- terminate()¶
停止子进程。
在POSIX系统上,此方法发送
signal.SIGTERM
到子进程。在Windows上,win32 api函数
TerminateProcess()
调用以停止子进程。
- kill()¶
停止子进程。
在POSIX系统上,此方法发送
SIGKILL
到子进程。在Windows上,此方法是的别名
terminate()
.
- stdin¶
标准输入流 (
StreamWriter
或None
如果进程是用stdin=None
.
- stdout¶
标准输出流 (
StreamReader
或None
如果进程是用stdout=None
.
- stderr¶
标准误差流 (
StreamReader
或None
如果进程是用stderr=None
.
警告
使用
communicate()
方法而不是process.stdin.write()
,await process.stdout.read()
或await process.stderr.read
. 这避免了由于流暂停读或写以及阻塞子进程而导致的死锁。- pid¶
工艺标识号(PID)。
请注意,对于由
create_subprocess_shell()
函数,此属性是生成的shell的PID。
- returncode¶
退出时返回进程的代码。
A
None
值表示进程尚未终止。负值
-N
指示子级已被信号终止N
(仅限POSIX)。
子进程和线程¶
默认情况下,标准异步事件循环支持从不同线程运行子进程。
在Windows上,子进程由提供 ProactorEventLoop
仅限(默认), SelectorEventLoop
没有子进程支持。
在Unix上 儿童观察者 用于子进程完成等待,请参见 过程观察者 更多信息。
在 3.8 版更改: Unix已切换使用 ThreadedChildWatcher
用于从不同线程生成子进程而不受任何限制。
用生成子进程 不活动 当前子观察程序提升 RuntimeError
.
请注意,可选的事件循环实现可能有自己的限制;请参考它们的文档。
实例¶
使用的示例 Process
类来控制子进程和 StreamReader
从其标准输出中读取的类。
子进程由 create_subprocess_exec()
功能:
import asyncio
import sys
async def get_date():
code = 'import datetime; print(datetime.datetime.now())'
# Create the subprocess; redirect the standard output
# into a pipe.
proc = await asyncio.create_subprocess_exec(
sys.executable, '-c', code,
stdout=asyncio.subprocess.PIPE)
# Read one line of output.
data = await proc.stdout.readline()
line = data.decode('ascii').rstrip()
# Wait for the subprocess exit.
await proc.wait()
return line
date = asyncio.run(get_date())
print(f"Current date: {date}")
也见 same example 使用低级API编写。