【问题标题】:Opposite of asyncio.to_thread与 asyncio.to_thread 相反
【发布时间】:2020-11-24 14:38:20
【问题描述】:

如何以阻塞方式运行异步函数?我不允许修改我的模拟函数 f1() 的签名,也不能轻易切换到 async def,因此不能使用 await 表达式。

async def cc2():
    await asyncio.sleep(1)
    await asyncio.to_thread(print, "qwerty")

def f1():
    t = asyncio.create_task(cc2())
    # wait until the task finished before returning

async def main():
    f1()  # typical call from many places of a program

asyncio.run(main())

我尝试了asyncio.get_running_loop().run_until_complete(t),但破解不起作用,我收到下一个错误。

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python3.9/asyncio/runners.py", line 44, in run
    return loop.run_until_complete(main)
  File "/usr/lib/python3.9/asyncio/base_events.py", line 642, in run_until_complete
    return future.result()
  File "<stdin>", line 2, in main
  File "<stdin>", line 3, in f1
  File "/usr/lib/python3.9/asyncio/base_events.py", line 618, in run_until_complete
    self._check_running()
  File "/usr/lib/python3.9/asyncio/base_events.py", line 578, in _check_running
    raise RuntimeError('This event loop is already running')
RuntimeError: This event loop is already running

【问题讨论】:

    标签: python python-asyncio


    【解决方案1】:

    如何以阻塞方式运行异步函数?

    如果您在同步代码中,您可以使用asyncio.run(async_function()) 调用它。如果你在异步代码中,你可以await async_function()asyncio.create_task(async_function()),后者安排它在后台运行。不允许在异步代码中使用 asyncio.run()(或 run_until_complete,即使是新创建的事件循环对象),因为它会阻塞并可能停止外部事件循环。

    但如果您需要它来进行测试,您可以随时执行以下操作:

    # XXX dangerous - could block the current event loop
    with concurrent.futures.ThreadPoolExecutor() as pool:
        pool.submit(asyncio.run, async_function()).result()
    

    【讨论】:

    • 感谢您对 ThreadPoolExecutor 的想法。正如预期的那样,这不是通用的解决方案,但是当协程是独立的并且不依赖于调用代码时,它是可以的,完全适合我的情况,特别是对于快速测试。
    • @mymedia 没错 - 这是一个严重的黑客攻击,但如果你知道你在做什么,它可以完成工作。 (您也可以使用普通线程,但是您必须手动传输返回值和异常,这就是我从 c.futures 提出执行程序的原因。)另一个选择是nest_asyncio 包,但我会避免这种情况一个是因为它使用monkeypatching来反对asyncio的明确设计决策,所以它比使用线程更像是一种黑客攻击。
    猜你喜欢
    • 2014-02-15
    • 2011-11-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-01
    • 2021-09-17
    • 1970-01-01
    • 2016-11-23
    相关资源
    最近更新 更多