在Python中设计异步API

Pav*_*aev 12 python asynchronous api-design future promise

(注意:这个问题严格关于API 的设计,而不是关于如何实现它;即我只关心我的API的客户端在这里看到了什么,而不是我必须做些什么才能使它工作.)

简单来说:我想知道已建立的模式 - 如果有的话 - 用于Python中的显式期货(也就是承诺,也就是延期,又称任务 - 名称因框架而异).以下是更详细的描述.

考虑一个像这样的简单Python API:

def read_line():
   ...
s = read_line()
print(s)
Run Code Online (Sandbox Code Playgroud)

这是一个同步版本 - 如果一条线路尚未可用,它将阻止.现在假设我想提供一个相应的异步(非阻塞)版本,它允许注册一个操作完成后调用的回调.例如,一个简单的版本可能如下所示:

def read_line_async(callback):
   ...
read_line_async(lambda s: print(s))
Run Code Online (Sandbox Code Playgroud)

现在,在其他语言和框架中,通常存在针对此类API的强制或至少完善的模式.例如,在版本4之前的.NET中,通常会提供一对BeginReadLine/ EndReadLine方法,并使用stock IAsyncResult接口注册回调并传递结果值.在.NET 4+中,人们使用System.Threading.Tasks,以便启用所有任务组合运算符(WhenAll等),并连接到C#5.0 async功能.

再举一个例子,在JavaScript中,标准库中没有任何内容可以覆盖它,但是jQuery已经推广了现在单独指定的"延迟promise"接口.因此,如果我readLine在JS中编写异步,我会命名它readLineAsync,并对then返回的值实现方法.

如果有的话,Python领域的既定模式是什么?通过标准库,我看到几个提供异步API的模块,但它们之间没有一致的模式,没有像"任务"或"承诺"的标准化协议.也许有一些模式可以从流行的第三方库中获得?

我也看过(在这个上下文中经常提到)Twisted中的Deferred类,但它似乎是一个通用的promise API过度设计,而是适应了这个库的特定需求.它看起来不像我可以轻松地克隆接口(不依赖于它们),这样如果客户端在他的应用程序中同时使用两个库,我们的promise将很好地互操作.是否有任何其他流行的库或框架具有明确设计的API,我可以复制(并与之互操作)而不需要直接依赖?

Pav*_*aev 6

好的,所以我找到了PEP-3148,它确实有一个Future类.就我所知,我不能完全按原样使用它,因为正确的实例只是由Executor它创建的,而且这是一个通过将同步调用移动到后台线程来将现有同步API转换为异步的类.但是,我可以完全复制Future对象提供的方法- 它们与我期望的非常接近,即(阻塞)查询结果,取消和添加回调的能力.

这听起来像是一种合理的方法吗?或许它应该伴随着向Python标准库添加通用"未来"概念的抽象基类的提议,就像Python集合拥有它们的ABC一样.

  • 经过进一步搜索,我找到了这个帖子 - http://mail.python.org/pipermail/python-ideas/2010-September/008054.html - 其中Guido确认`concurrent.futures.Future`是正确的选择. (3认同)