【问题标题】:async - sync - async calls in one python event loopasync - 同步 - 在一个 python 事件循环中进行异步调用
【发布时间】:2017-12-26 01:23:06
【问题描述】:

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

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 的使用,它使您更改所有项目。告诉我这不是真的。

【问题讨论】:

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


    【解决方案1】:

    来吧!它让你因为一个 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

    【讨论】:

    • 这两个独立的世界,sync 和 async,让过渡到 asyncio 变得非常复杂 :( 也许我会在创建完全异步工具后改变主意。无论如何,谢谢你的回答。
    • 对于在基于 asyncio 的新代码和同步遗留代码之间共享的库来说,这是一种很好的方法。
    • 但是你只能使用一次 run_until_complete() 因为 asyncio 不支持嵌套的异步调用...如果有多个异步函数,上述方法将不起作用。
    • 对于我的用例来说,只有一个事件循环会破坏交易。如果有其他解决方案感兴趣。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-04-10
    • 2023-03-05
    • 2019-01-29
    • 2021-12-12
    • 1970-01-01
    • 2018-09-18
    • 1970-01-01
    相关资源
    最近更新 更多