在Python中设计异步API
(注意:这个问题主要是关于API的设计,而不是如何实现它;也就是说,我只关心我的API的使用者看到的内容,而不是我需要做什么才能让它工作。)
简单来说:我想了解在Python中关于显式未来(也叫承诺、延迟、任务 - 名字根据框架不同而不同)的已有模式。如果有的话,以下是更详细的描述。
考虑一个简单的Python API,如下所示:
def read_line():
...
s = read_line()
print(s)
这是一个同步版本 - 如果一行数据还没有准备好,它会阻塞等待。现在,假设我想提供一个对应的异步(非阻塞)版本,允许注册一个回调函数,在操作完成后调用它。例如,一个简单的版本可能看起来像这样:
def read_line_async(callback):
...
read_line_async(lambda s: print(s))
在其他语言和框架中,通常会有一些现成的或至少是公认的模式来处理这样的API。例如,在.NET 4之前,通常会提供一对BeginReadLine
/EndReadLine
方法,并使用标准的IAsyncResult
接口来注册回调和传递结果值。在.NET 4及以上版本中,使用System.Threading.Tasks
,以便启用所有任务组合操作符(WhenAll
等),并与C# 5.0的async
特性结合使用。
再举个例子,在JavaScript中,标准库没有覆盖这个内容,但jQuery普及了“延迟承诺”接口,现在已经单独规范化。所以如果我在JS中编写异步的readLine
,我会把它命名为readLineAsync
,并在返回值上实现then
方法。
那么,在Python中,有没有什么公认的模式呢?浏览标准库时,我看到几个模块提供异步API,但它们之间没有一致的模式,也没有类似于“任务”或“承诺”的标准协议。也许可以从一些流行的第三方库中推导出某种模式?
我还看到在这个上下文中经常提到的Deferred类在Twisted中,但它似乎为通用的承诺API设计得过于复杂,更适应于这个库的特定需求。看起来我很难轻松地克隆一个接口(而不依赖于它们),以便我们的承诺能够很好地与客户端在应用中同时使用这两个库进行交互。有没有其他流行的库或框架,专门为此设计了API,我可以在不直接依赖的情况下进行复制(并实现互操作)?
3 个回答
你有没有看过装饰器呢?
from threading import Thread
def addCallback(function):
def result(parameters,callback):
# Run the function.
result = function(parameters)
# Run the callback asynchronously.
Thread(target=callback).start()
# Run the callback synchronously.
#callback()
# Return the value of the function.
return result
return result
@ addCallback
def echo(value):
print value
def callback():
print 'Callback'
echo('Hello World!',callback)
可以看看各种“服务器”库,里面有很多提示。
一个很好的例子是 BaseHTTPServer。
特别是 HTTPServer 这个类的定义,展示了如何提供一个“处理器类”。
每次请求都会创建一个处理器类的实例。这个对象就会处理这个请求。
如果你想写“异步输入输出”,并使用“回调”,你需要给你的读取器提供一个 ReadHandler
类。
class AsyncReadHandler( object ):
def input( self, line, server ):
print( line )
read_line_async( AsyncReadHandler )
这样的做法会遵循一些已经建立的设计模式。