我现在有一个打开子进程的设置,我必须同时读取stdout和stderr ,所以在调用子进程之后,我为stdout生成了一个新线程,并在主线程中处理stderr。
# imports
from subprocess import Popen, PIPE
from threading import Thread
def handle_stdout(stdout):
# ... do something with stdout,
# not relevant to the question
pass
def my_fn():
proc = Popen([...], stdout=PIPE, stderr=PIPE)
Thread(target=lambda: handle_stdout(proc.stdout)).start()
# ... handle stderr
print(proc.stderr.read())
proc.wait()
proc.kill()
my_fn()有什么方法可以用异步实现同样的目标吗?
发布于 2020-02-01 01:54:19
您的代码的无线程asyncio版本可能如下所示:
import asyncio
import asyncio.subprocess
async def handle_stdout(stdout):
while True:
line = await stdout.readline() # Possibly adding .decode() to get str
if not line:
break
# In 3.8 four lines above can be replaced with just:
# while line := await stdout.readline(): # Yay walrus operator!
# ... do stuff with line ...
async def my_fn():
# Note: No list wrapping on command line arguments; all positional arguments are part of the command
proc = await asyncio.create_subprocess_exec(..., stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE)
stdout_task = asyncio.create_task(handle_stdout(proc.stdout))
# ... handle stderr
print(await proc.stderr.read())
await stdout_task
await proc.wait()
if __name__ == '__main__':
asyncio.run(my_fn())API有点不同,当您使用异步函数执行任务时(线程必须接受未调用的函数),异步函数实际上会被调用,您需要小心地await所执行的所有异步操作,但这并没有什么不同。主要问题是async的病毒特性;因为您只能在async函数中调用异步代码,所以很难从非异步代码调用异步代码(相反,只要非异步代码不因任何原因而阻塞)。它使得异步代码基本不兼容非异步代码,并且几乎不可能进行零敲碎打的转换,但对于全新的代码来说,它工作得很好。
https://stackoverflow.com/questions/59987124
复制相似问题