如何在python中选择异步或同步方法变体? [英] How to choose asynchronous or synchronous method variants in python?

查看:183
本文介绍了如何在python中选择异步或同步方法变体?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我有一个用于执行I/O操作的类:

Let's assume I have a class that is used to perform I/O operations:

class CommunicationStack:
    def __init__(self, socket):
        self.socket = socket

    def sync_get_data(self):
        ...

    def sync_send_data(self):
        ...

    async def async_get_data(self):
        ...

    async def async_send_data(self):
        ...

如您所见,它具有同步和异步变体,用于相同的操作,但是手动编写async_get_datasync_get_data会有些不便.我正在寻找一种具有相同界面的聪明方法,例如

As you can see it has sync and async variant for the same operations but it would be slightly inconvenient to write async_get_data or sync_get_data manually. I am looking for a smart way to have the same interface like

def get_data(self):
    ...  # call sync variant or return an awaitable, depending on caller type

def send_data(self):
    ...  # call sync variant or return an awaitable, depending on caller type

因此可以像这样方便地使用它:

so it can be conveniently used like:

stack = CommunicationStack(...)

def thread_procedure():
    data = stack.get_data()  # get_data returns data

async def task_procedure():
    data = await stack.get_data()  # get_data returns an awaitable

我相信可以通过检查或某些黑魔法:

I believe it can be done in some tricky way with inspections or some black magic:

def is_caller_coroutine():
    return sys._getframe(2).f_code.co_flags & 0x380

检查调用程序是协程还是函数,但是弄乱python的胆量似乎是一个糟糕的设计.

to check if caller is a coroutine or a function but it seems like a bad design to mess with python's guts.

问题是:选择合适的变体的好方法是什么?还是有更好的方法来设计一切,例如使用适配器或开发两个独立的AsyncCommunicationStack SyncCommunicationStack类?

The question is: what is a good way to choose appropriate variant? Or is there a better way to design everything like using adapters or developing two independent AsyncCommunicationStack and SyncCommunicationStack classes?

推荐答案

如果您希望以与常规函数相同的方式调用异步函数,则可能对使用

If you want to call async functions same way as regular ones, you may be interested in using gevent.

asyncio希望您将函数显式标记为async,并在发生异步操作的任何地方显式使用await.换句话说,asyncio希望您具有用于同步和异步代码的不同接口.

asyncio wants you to explicitly mark functions as async and to explicitly use await everywhere async stuff happens. In other words asyncio wants you to have different interfaces for sync and async code.

这是有意做出的决定,用于解决并发问题,而当代码具有异步性质时,这是很难实现的.隐藏(如gevent).

This is intentional decision made to fight with concurrency problems which is much harder to achieve when async nature of a code is hidden (like in gevent).

所以是的-如果您想同时支持两个世界,则可以使用两种不同的独立AsyncCommunicationStackCommunicationStack类.虽然一旦有了异步版本,您就可以使用它强制转换关键代码并使其同步,只需使用

So yes - two different independent AsyncCommunicationStack and CommunicationStack classes is a way to go if you want to support both worlds. Although once you have async version you can cast write critical code with it and make it sync just running it with asyncio.run(). Problem only is that you won't be able to return to async world after that.

这篇关于如何在python中选择异步或同步方法变体?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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