我正在使用一个非异步库,该库不执行I / O,仅执行简单的计算。它的功能之一是在一组用户提供的观察者上按其发生的顺序进行一系列的回调,而用户则控制一个更高级别的api。
class Calculator:
def __init__(self):
self._internal = 0
self._observers = [
def register(observer):
self._observers.append(observer)
def add(int val):
for i in range(val):
self._internal += 1
def _call_observers(self):
for o in self._observers:
o.on_add()
@property
def value(self):
return self._internal
我需要在一个协程中使用它来调用其他协程。我曾经有一个想法是将AsyncCalculator
子类化,并将相关方法重写为协程,并存储对事件循环的引用。
(不是真实代码)
class AsyncCalculator(Calculator):
def __init__(self, loop):
...
async def _call_observers(self):
...
我想知道是否有一种方法可以从常规函数中等待协程,是否有对事件循环或任何其他可用结构的引用?似乎如果从协程中调用该函数,则可能会有一些怪异的方法来等待该函数中的另一个协程。那也许可以将这种黑客扔进一个工具中?
答案 0 :(得分:1)
如果正在运行的事件循环中调用Calculator
方法,则可以指示协程从同步函数中恢复。 (Asyncio始终在内部执行此类操作。)为此,您无需使_call_observers
异步,可以执行以下操作:
class _Observer:
def __init__(self, fut):
self.fut = fut
def on_add(self):
self.fut.set_result('add')
async def my_coro(calc):
loop = asyncio.get_event_loop()
fut = loop.create_future()
calc.register(_Observer(fut))
# wait for the observer to be invoked
op = await fut
if op == 'add':
...
这要求整个事件都在事件循环内运行,无论是否发生IO。