asyncio:如何将同步代码组合起来,而不强制完全使用asyncio

6

看起来Python的asyncio库是一种全新的解决方案。特别地,它似乎强制整个调用栈都具有异步处理能力。

下面是一个例子:

假设由函数 a() 实现了某个算法。
该算法调用了函数 b()

def a(b):
  for i in ...:
    # do smth...
    res = b()
    # do smth more ...

现在假设函数b()在不同的环境下可能有不同的实现,而且可能希望在异步事件循环中调用a()(使用loop.call_soon()),其中b()调用了一些支持asyncio的代码:

def b():
   await .... # this forces b() to be declared async.

现有事件循环似乎被明确禁止使用...那么,有没有方法可以实现这个功能,而不需要将整个堆栈 (a()b()) 明确定义为异步协程?


1
似乎Python的asyncio是一种全有或全无的交易。具体来说,它似乎强制整个调用堆栈都要支持异步。-- 是的。所有的async堆栈都是这样的。 - Robert Harvey
Gevent提供了更多的灵活性。我喜欢它的原因是,你不必一定编写异步代码来使它异步化。特别是在WSGI方面。只需要一个简单的spawn就可以让它异步化。 - eatmeimadanish
1个回答

6
虽然异步编程(asyncio)在表面上是一个全新的概念,但是我们仍有两个应急措施,可以帮助处理遗留或异构环境:
  • 在asyncio中,您可以使用loop.run_in_executor(callable, args...)在另一个线程中运行同步代码,并暂停当前协程,直到结果准备好。
  • 在asyncio之外,您可以使用asyncio.run_coroutine_threadsafe()将协程提交给在另一个线程中运行的事件循环。它立即返回一个concurrent.futures未来对象,该对象具有阻止result()方法,可以在不影响事件循环的情况下阻塞当前线程。(使用run_coroutine_threadsafe需要事先在专用线程中启动事件循环.)
拥有这两个工具,就不难将异步编程和经典同步代码混合使用。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接