如何将 trio_asyncio 与 python 中的旧同步代码一起使用

How to use trio_asyncio with legacy sync code in python

我有旧版 python 同步应用程序。 我开始以这种方式(简化)在此应用程序中使用异步代码:


async def loader():
  async with trio.open_nursery() as nursery:
    # some async tasks started here
    await trio.to_thread.run_sync(legacyCode)
    

if __name__ == '__main__':
  trio.run(loader)

legacyCode 内部,我可以使用 trio.from_thread.run(asyncMethod) 到 运行 来自遗留同步代码的一些异步代码。 它运行良好,但现在我需要包含内部使用 trio_asyncio.

的新库 (triopg)

所以我需要修改启动应用程序的方式 - 我需要用 trio_asyncio.run 替换 trio.run。这很简单,但是在 trio.to_thread -> trio.from_thread 之后,异步代码不起作用,因为 trio_asyncio 没有定义循环。

这是一个简短的演示:

import trio
import trio_asyncio

def main():
  trio.from_thread.run(amain)

async def amain():
  print(f"Loop in amain: {trio_asyncio.current_loop.get()}")  # this print none

async def loader():
  print(f"Loop in loader: {trio_asyncio.current_loop.get()}")  # this print some loop
  await trio.to_thread.run_sync(main)

if __name__ == '__main__':
  trio_asyncio.run(loader)

我应该如何修改上面的示例,以便 trio_asyncio 能够在 amain() 函数中找到循环? 还是这种做法完全错误?如果是这样,当库需要使用 triotrio_asyncio 时,我如何在巨大的同步应用程序中使用小块异步代码?

我用的是python3.9.

我终于找到了解决方案,而且……看起来很简单:-)

当我们从线程调用异步函数时,需要手动打开trio_asyncio循环。所以唯一的区别是在 amain() 函数中添加 open_loop() 调用:

import trio
import trio_asyncio


def main():
  trio.from_thread.run(amain)


async def amain():
  async with trio_asyncio.open_loop():
    print(f"Loop in amain: {trio_asyncio.current_loop.get()}")  # this print another loop


async def loader():
  print(f"Loop in loader: {trio_asyncio.current_loop.get()}")  # this print one loop
  await trio.to_thread.run_sync(main)


if __name__ == '__main__':
  trio_asyncio.run(loader)