简体   繁体   English

使用 asyncio 同时执行两个函数

[英]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.我现在有一个设置,其中我打开一个子,我要读这两个stdoutstderr在同一时间,所以调用子后,我催生一个新的线程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.

相关问题 在 python asyncio 中并发运行函数 - Running functions concurrently in python asyncio asyncio - 函数按顺序运行而不是同时运行 - asyncio - functions run sequentially instead of concurrently 使用asyncio创建两个并发异步任务 - Create two concurrently async task with asyncio 为什么使用 Asyncio 不会减少 Python 中的整体执行时间并同时运行函数? - Why using Asyncio is not reducing the overall execution time in Python and run functions concurrently? asyncio.create_task 装饰器不会同时执行 - asyncio.create_task decorator doesn't execute concurrently 在 python 中同时运行两个函数 - Run two functions concurrently in python 如何使用 asyncio 运行两个函数? - How to run two functions with asyncio? 如何同时执行两个“聚合”函数(如 sum),并从同一个迭代器提供它们? - How to execute two “aggregate” functions (like sum) concurrently, feeding them from the same iterator? 如何在大管理器中同时运行异步启动器/同时运行异步功能 - How to concurrently run asynchronous launchers/concurrently run asyncio functions in a big manager Python - 如何使用asyncio同时运行多个协同程序? - Python - how to run multiple coroutines concurrently using asyncio?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM