python - 在 python 子进程中检测关闭的非阻塞 stdout/stderr 管道
问题描述
我正在使用 Python 以交互方式运行进程。
p = Popen ("/path/to/my-executable", stdin=PIPE, stdout=PIPE, stderr=PIPE, bufsize=1)
for f in (p.stdout, p.stderr):
flags = fcntil.fcntl (f, fcntl.F_GETFL) | os.O_NONBLOCK
fcntl.ftcntl (f, flags)
for line in sys.stdin:
p.stdin.write (line.encode ('utf-8'))
...
假设我从 stdin 读取命令并将其转发到my-executable
via p
,此过程可能会或可能不会向 stdout/stderr 输出任何内容,并且它可能会或可能不会终止。
我想等到my-executable
“做某事”后再从标准输入读取另一个命令。
我尝试将此bash
作为子进程并"exit"
写入line
其标准输入,当我从其标准输出和 sterr 读取时,标准输出None
和标准错误给出b''
但我不希望这是一个进程已完成运行的可靠指示(即我不能合理p.wait()
,因为该结果中没有任何内容可以决定性地告诉我该过程不会再提供任何输出)。
我如何正确地让这个 Python 脚本等到
- 某些内容被写入 stdout 或 stderr 或
- stdout 或 stderr 已关闭
?
解决方案
您可以使用selectors
它,如下所示:
# one-time setup
import selectors
sel = selectors.DefaultSelector()
sel.register(p.stdout, selectors.EVENT_READ)
sel.register(p.stderr, selectors.EVENT_READ)
# each time you want to wait
sel.select()
不过,我建议您使用无缓冲 I/O,而不是行缓冲 I/O。此外,您可以os.set_blocking(f.fileno(), False)
让您的 FD 无阻塞,而不必自找麻烦fcntl
。
推荐阅读
- list - 这个 Common Lisp 代码是否与 Winston / Horn 在 LISP 3rd Edition 中所教的内容相似/相等?
- python - 显示包含字符和空格以外的其他内容的文本数据框行(Python)
- node.js - 如果用户有 cookie,则对用户进行身份验证
- python - 想知道为什么我的 GUI 检查按钮功能不起作用?
- next.js - 提供者为 Auth0 时,下一个身份验证登录失败并出现 oauth_get_access_token_error 和 callback_oauth_error 错误
- sql - 在 2 个不同的服务器上加入 2 个表
- android - Unity 自动构建和安装到多个 Android
- performance - 为什么这个函数在额外读取内存时运行得这么快?
- python - 当图形保存为 PDF 时,dpi 是否相关?
- python - 跨模块共享全局变量最佳实践