[英]Execute two functions concurrently using asyncio
I currently have a setup where I open a subprocess and I have to read both stdout
and stderr
at the same time , so after invoking the subprocess I spawn a new thread for stdout
and just handle stderr
in the main thread.我现在有一个设置,其中我打开一个子,我要读这两个
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()
Is there a way I can achieve the same thing using asyncio?有没有办法使用 asyncio 实现同样的目标?
A thread-free asyncio
version of your code might look something like this:代码的无线
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())
The APIs are a little different, async functions are actually called when you make tasks from them (where threads must take uncalled functions), and you need to be careful to await
all async actions taken, but it's not that different. API 略有不同,异步函数实际上是在您从它们中创建任务时调用的(线程必须执行未调用的函数),并且您需要小心地
await
所有异步操作,但这并没有什么不同。 The main issue is async
's viral nature;主要问题是
async
的病毒性质; since you can only await
in an async
function, it's hard to call async code from non-async code (the other way around works fine, as long as the non-async code doesn't block for any reason).由于您只能在
async
函数中await
,因此很难从非异步代码调用异步代码(反之亦然,只要非异步代码不会因任何原因阻塞)。 It makes async code bases largely incompatible with non- async
stuff, and makes converting piecemeal nearly impossible, but for brand new code, it works fine.它使异步代码库在很大程度上与非
async
内容不兼容,并使零碎的转换几乎不可能,但对于全新的代码,它工作正常。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.