异步 - 同步 - 在一个python事件循环中调用异步

时间:2017-07-20 11:16:33

标签: python python-3.x python-asyncio aiohttp

假设我有一个内部使用asyncio循环的类,并且没有异步接口:

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可以帮助我。没有支持both interfaces,真的没有办法做到这一点吗?来吧!它使您可以更改所有项目,因为有一个asyncio用法。告诉我这不是真的。

1 个答案:

答案 0 :(得分:5)

  

来吧!它会让你因为一个asyncio而改变你的所有项目   用法。告诉我这不是真的。

确实如此:)

使用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