异步-同步-在一个python事件循环中异步调用 [英] async - sync - async calls in one python event loop

查看:95
本文介绍了异步-同步-在一个python事件循环中异步调用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Let's say I have a class which uses asyncio loop internally and doesn't have async interface:

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

我在内部使用了asyncio的所有优点,不必在意

I use all advantages of asyncio internally and don't have to care about it in the outer code.

但是我想在一个事件循环中调用3个 Fetcher 实例。如果我有 async def 界面,就不会有问题: asyncio.gather 可以帮助我。如果不同时支持两个接口,是否真的没有其他方法可以做到?来吧!它使您由于一次异步使用而更改了所有项目。告诉我这不是真的。

But then I want to call 3 Fetcher instances in one event loop. If I had async def interface there would be no problem: asyncio.gather could help me. Is there really no other way to do it without supporting both interfaces? Come on! It makes you change all your project because of one asyncio usage. Tell me this is not true.

推荐答案


来吧!由于使用asyncio
,它使您可以更改所有项目。告诉我这不是真的。

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

是真的

完整的想法使用 await 关键字是在一个事件循环中从代码的不同位置执行并发作业(您不能使用常规功能代码执行此操作)。

Whole idea of using await keyword is to execute concurrent jobs in one event loop from different places of the code (which you can't do with regular function code).

asyncio -不是一些实用程序,而是整个编写异步程序的样式。

asyncio - is not some utility, but whole style of writing asynchronous programs.

另一方面,Python非常灵活,因此您仍然可以尝试隐藏对asyncio的使用。如果您确实想要获取3个Fetcher实例的同步结果,则可以执行以下操作:

On the other hand Python is very flexible, so you can still try to hide using of asyncio. If you really want to get sync result of 3 Fetcher instances, you can for example do something like this:

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]

但是,再次相信,如果您继续以此方式编写代码,您一定会后悔的,相信我。如果要充分利用异步编程的优势,请显式使用协程 await

But, again, you'll really regret someday if you continue to write code this way, believe me. If you want to get full advantage of asynchronous programming - use coroutines and await explicitly.

这篇关于异步-同步-在一个python事件循环中异步调用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆