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

时间:2015-06-30 20:59:47

标签: python buffering

我正在编写一个使用

的相当复杂的脚本
asyncio.create_subprocess_exec(sub_cmd, *sub_cmd_args, stdout=PIPE, stderr=PIPE)

包装另一个Python程序 - 我无法永久修改或直接包含 - 捕获其stdout / err以进行日志记录。包装的Python脚本没有使用-u(无缓冲)选项,因此包装器程序倾向于登录大缓冲块。如果这是常规子进程.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

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

1 个答案:

答案 0 :(得分:1)

我首先向自己证明,通过将-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'})

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