python - 如何在python中选择异步或同步方法变体?
问题描述
假设我有一个用于执行 I/O 操作的类:
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_data
或sync_get_data
手动操作会有些不便。我正在寻找一种聪明的方式来拥有相同的界面
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
所以它可以方便地使用,如:
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
我相信它可以通过检查或一些黑魔法以某种棘手的方式完成:
def is_caller_coroutine():
return sys._getframe(2).f_code.co_flags & 0x380
检查调用者是协程还是函数,但是弄乱python的胆量似乎是一个糟糕的设计。
问题是:选择合适的变体的好方法是什么?或者有没有更好的方法来设计一切,比如使用适配器或开发两个独立AsyncCommunicationStack
的和SyncCommunicationStack
类?
解决方案
如果您想以与常规函数相同的方式调用异步函数,您可能对使用gevent感兴趣。
asyncio
希望您将函数显式标记为async
并显式使用await
异步内容发生的任何地方。换句话说asyncio
,希望您对同步和异步代码有不同的接口。
这是为了解决并发问题而做出的有意决定,当代码的异步性质被隐藏时(例如在 gevent 中),这很难实现。
所以是的 -如果你想支持两个世界,两个不同的独立AsyncCommunicationStack
和类是一种方法。CommunicationStack
虽然一旦你有了异步版本,你就可以使用它来编写关键代码并使其同步,只需使用asyncio.run()运行它。唯一的问题是在那之后您将无法返回异步世界。
推荐阅读
- excel - 从多张工作表复制Excel不起作用vba
- jdbc - 是否可以使用 Kafka Connect 在 Kafka 中“更新”消息?
- python - 将文本用户输入作为字符串传递给另一个函数
- angular6 - 在 Angular 6 中使用 sessionStorage 的最佳方法是什么
- python-3.x - 使用 BioPython 修剪 fasta 文件
- javascript - 一页中的多个 googleMaps 具有非顺序 ID
- php - 用phpexcel保存到临时文件
- python-3.x - 散景 - ColumnDataSource 不更新胡须图
- api - 通过 Azure API 管理生成访问令牌并针对 IdentityServer4 进行验证
- laravel - 如何解决“关系‘a’不是 HasOne 或 BelongsTo 的实例。” 在 laravel 里?