使用asyncio子进程时是否可以设置管道的缓冲区大小?

JFl*_*Flo 5 python buffering

我正在写一个相当复杂的脚本正在使用

asyncio.create_subprocess_exec(sub_cmd, *sub_cmd_args, stdout=PIPE, stderr=PIPE)
Run Code Online (Sandbox Code Playgroud)

包装另一个Python程序 - 我无法永久修改或直接包含 - 捕获其stdout/err进行日志记录.包装的Python脚本没有使用-u(unbuffered)选项,因此包装器程序倾向于登录大缓冲块.如果这是常规子进程.Popen我可以传递bufsize=1给我想要的东西,即行缓冲.但是,如果我将它添加到asyncio.create_subprocess_exec(),他们会特意陷阱,我得到:

<snip>
  File "/usr/lib64/python3.4/asyncio/subprocess.py", line 193, in create_subprocess_exec
    stderr=stderr, **kwds)
  File "/usr/lib64/python3.4/asyncio/base_events.py", line 642, in subprocess_exec
    raise ValueError("bufsize must be 0")
ValueError: bufsize must be 0
Run Code Online (Sandbox Code Playgroud)

我认为他们的陷阱是有充分理由的,所以我想知道是否还有其他一些方法可以影响传输缓冲.

JFl*_*Flo 6

-u我首先通过添加到包装程序的 shebang 行来向自己证明这确实是一个管道缓冲问题。但我不能依赖它作为解决方案,因为这样的更改最终会被操作系统更新所破坏。

我能够以类似的方式解决这个问题:

  • 包装程序是管道的父程序,因此它控制其子程序的环境。
  • Python 在其继承的环境中应该遵守PYTHONUNBUFFERED=1
  • asyncio.create_subprocess_exec()确实支持一个env=论点以及大多数可以传递给的其他内容subprocess.Popen();也许记录不足,但查看代码就可以很明显地看出这一点。

所以我将电话更改为:

asyncio.create_subprocess_exec(sub_cmd, *sub_cmd_args, stdout=PIPE, stderr=PIPE, env={'PYTHONUNBUFFERED': '1'})
Run Code Online (Sandbox Code Playgroud)

这非常有效,这要归功于我的好朋友和技术大师。