PEP 3145 – subprocess.Popen 的异步 I/O
- 作者:
- Eric Pruitt,Charles R. McCreary,Josiah Carlson
- 状态:
- 已撤回
- 类型:
- 标准轨迹
- 创建:
- 2009年8月4日
- Python 版本:
- 3.2
- 历史记录:
摘要
在当前形式下,subprocess.Popen
的实现容易导致死锁,并在等待子进程数据时阻塞父 Python 脚本。本 PEP 提出使 subprocess.Popen
更加异步,以帮助缓解这些问题。
PEP 推迟
对本 PEP 中涵盖的概念的进一步探索已被推迟,至少要等到 PEP 3156 解决之后。
PEP 撤回
这可以在错误跟踪器中处理。一个具体的提案附在 [11] 中。
动机
搜索“python asynchronous subprocess”将显示许多人希望执行子进程并不时与其通信,仅读取可用数据而不是阻塞以等待程序生成数据的记录 [1] [2] [3]。subprocess
模块的当前行为是,当用户通过 stdin、stderr 和 stdout 文件对象发送或接收数据时,死锁很常见且有记录 [4] [5]。虽然可以使用 communicate 来缓解一些缓冲问题,但当没有数据可从子进程读取时,它仍然会导致父进程在尝试读取数据时阻塞。
基本原理
有记录表明 subprocess.Popen
中需要异步、非阻塞功能 [6] [7] [2] [3]。包含代码将提高 Python 标准库的实用性,该库可用于基于 Unix 和 Windows 的 Python 版本。实际上,Python 中的每个 I/O 对象都具有一种或另一种文件式包装器。套接字已经充当这种角色,对于字符串,有 StringIO
。只需使用附加到 subprocess.Popen.stderr
、stdout 和 stdin 文件式对象的 method,就可以使 Popen 充当文件。但是,当使用这些选项的 read 和 write 方法时,您将无法获得异步 I/O 的好处。在提出的解决方案中,包装器包装了异步方法以模仿文件对象。
参考实现
我一直维护着一个 Google Code 代码库,其中包含我的所有更改,包括测试和文档 [9],以及详细说明我在开发过程中遇到的问题的博客 [10]。
我一直致力于在 subprocess
模块中实现非阻塞异步 I/O,以及一个用于 subprocess.Popen
的包装类,它使执行的进程可以通过复制文件对象的所有方法和属性来代替文件。
已向 subprocess.Popen
类添加了两个基本函数:Popen.send
和 Popen._recv
,每个函数都有两个单独的实现,一个用于 Windows,一个用于基于 Unix 的系统。Windows 实现使用 ctypes 以异步方式访问内核 32 DLL 中控制管道所需的函数。在基于 Unix 的系统上,Python 文件控制接口具有相同的用途。Popen.send
和 Popen._recv
的不同实现具有相同的参数,以使使用这些函数的代码能够跨多个平台工作。
调用 Popen._recv
函数时,它需要将管道名称作为参数传递,因此存在 Popen.recv
函数,该函数默认将 stdout 作为 Popen._recv
的管道。 Popen.recv_err
默认将 stderr 作为管道。 Popen.recv
和 Popen.recv_err
比 Popen._recv('stdout' ...)
和 Popen._recv('stderr' ...)
分别更容易阅读和理解。
由于 Popen._recv
函数在返回值之前不会等待生成数据,因此它可能会返回空字节。 Popen.asyncread
通过在给定时间间隔内返回所有读取的数据来处理此问题。
ProcessIOWrapper
类使用 asyncread
和 asyncwrite
函数允许进程充当文件,从而不会出现使用 subprocess.Popen
调用生成的 stdout 和 stdin 文件对象可能出现的阻塞问题。
参考文献
[8] subprocess.rst - subprocdev - Google Code 上的项目托管 https://web.archive.org/web/20130306074135/http://code.google.com/p/subprocdev/source/browse/doc/subprocess.rst?spec=svn2c925e935cad0166d5da85e37c742d8e7f609de5&r=2c925e935cad0166d5da85e37c742d8e7f609de5
版权
本 PEP 采用开放出版许可证授权; http://www.opencontent.org/openpub/。
来源: https://github.com/python/peps/blob/main/peps/pep-3145.rst
上次修改时间: 2023年9月9日 17:39:29 GMT