0

我有一个带有以下伪代码的简单 python 函数:

while True:

    # 1 - CPU Intensive calculations(Synchronous)
    
    
    # 2 - Take the result from the synchronous calculation and POST it to a server

while 循环永远运行,并在循环的前半部分进行 CPU 密集型计算。所有这些都是同步运行的,没关系。我想做的是通过使 POST 请求异步来节省一些时间。while 循环需要永远运行,但是我希望异步发出请求,以便循环可以继续下一次迭代,而无需等待请求解决。

想知道在不使用任何额外线程/greenlets/processes 的情况下使用 asyncio 实现这一目标的最佳方法是什么

编辑


在这里发布问题之前,我已经尝试过这种方法:

async def example_function():
    # Synchronous CPU Intensive calculations

    client = httpx.AsyncClient()
    # Make a call to the REST API
    await client.post()


async def main():
    while True:
        await asyncio.gather(example_function(), example_function())


if __name__ == "__main__":
    asyncio.run(main())

我对使用 python 进行异步编程完全陌生。我尝试了收集方法,但是我的实现方法的缺陷是 example_function() 的第二次迭代不会异步生成 POST req。我知道 asyncio.gather() 基本上为传递给它的每个函数安排了一个任务,我有一个任务在等待,它继续执行下一个任务。但是,我需要永远在循环中运行 example_function() 而不仅仅是n

4

1 回答 1

1

想知道在不使用任何额外线程/greenlets/processes 的情况下使用 asyncio 实现这一目标的最佳方法是什么

如果您的代码是同步的,您将需要使用某种形式的多线程,但您可以通过 asyncio 为此目的提供的线程池以干净的方式执行此操作。例如,如果您通过 运行同步代码loop.run_in_executor(),则事件循环将在计算运行时保持旋转,并且将为放置在后台的任务提供服务。这使您可以使用asyncio.create_task()在后台运行循环的第二部分,或者更准确地说,与事件循环的其余部分并行运行。

def calculations(arg1):
    # ... synchronous code here

async def post_result(result, session):
    async with session.post('http://httpbin.org/post',
                            data={'key1': result}) as resp:
        resp.raise_for_status()

async def main():
    loop = asyncio.get_event_loop()

    with aiohttp.ClientSession() as session:
        while True:
            # run the sync code off-thread so the event loop
            # continues running, but wait for it to finish
            result = await loop.run_in_executor(None, calculations, arg1)

            # don't await the task, let it run in the background
            asyncio.create_task(post_result(result, session))

if __name__ == '__main__':
    asyncio.run(main())
于 2020-07-09T16:35:49.807 回答