【问题标题】:Python asyncio - can I call a coroutine from a function?Python asyncio - 我可以从函数中调用协程吗?
【发布时间】:2018-09-11 01:06:07
【问题描述】:

我正在使用一个不进行 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):
        ...

我想知道如果有对事件循环或任何其他可用结构的引用,是否有办法从普通函数等待协程?似乎如果该函数是从协程调用的,那么可能有一些骇人听闻的方法来等待来自该函数的另一个协程。那么也许这个 hack 可以被扔进一个实用程序中?

【问题讨论】:

    标签: python-asyncio


    【解决方案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。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-10-16
      • 1970-01-01
      • 2018-07-08
      • 2016-03-27
      • 2021-06-07
      • 1970-01-01
      • 2016-07-30
      • 1970-01-01
      相关资源
      最近更新 更多