async - sync - 在一个 python 事件循环中进行异步调用

async - sync - async calls in one python event loop

假设我有一个 class,它在内部使用异步循环并且没有异步接口:

class Fetcher:
    _loop = None
    def get_result(...):
        """
        After 3 nested sync calls async tasks are finally called with *run_until_complete*
        """
        ...

我在内部使用了asyncio的所有优点,而不必在外部代码中关心它。

但是我想在一个事件循环中调用 3 个 Fetcher 实例。如果我有 async def 界面就没有问题: asyncio.gather 可以帮助我。不支持就真的没有别的办法了吗?来吧!它会让你因为一次 asyncio 使用而改变你的所有项目。告诉我这不是真的。

Come on! It makes you change all your project because of one asyncio usage. Tell me this is not true.

这是真的

使用 await 关键字的整个想法是从代码的不同位置在一个事件循环中执行并发作业(使用常规函数代码无法做到这一点)。

asyncio - 不是一些实用程序,而是编写异步程序的整体风格。


另一方面 Python 非常灵活,所以你仍然可以尝试隐藏 asyncio 的使用。如果你真的想获得 3 个 Fetcher 实例的同步结果,你可以这样做:

import asyncio


def sync_exec(coro):
    loop = asyncio.get_event_loop()
    return loop.run_until_complete(coro)


class Fetcher:
    async def async_get_result(self):
        # async interface:
        async def async_job():
            await asyncio.sleep(1)
            return id(self)
        return (await async_job())

    def get_result(self):
        # sync interface:
        return sync_exec(self.async_get_result())

    @classmethod
    def get_results(cls, *fetchers):
        # sync interface multiple:
        return sync_exec(
            asyncio.gather(*[fetcher.async_get_result() for fetcher in fetchers])
        )        



# single sync get_result:
f1 = Fetcher()
print('Result: ', f1.get_result())


# multiple sync get_result:
f2 = Fetcher()
f3 = Fetcher()
print('Results: ', Fetcher.get_results(f1, f2, f3))

输出:

Result:  2504097887120
Results:  [2504097887120, 2504104854416, 2504104854136]

但是,再一次,如果你继续这样写代码,总有一天你会后悔的,相信我。如果您想充分利用异步编程 - 明确使用 coroutinesawait