Python中的异步函数调用
在Python中,我想在一个类里创建一个异步方法,这个方法可以启动一个线程,而不会阻塞主线程。等这个新线程完成后,我想从那个函数/线程中返回一个值。
举个例子,这个类是用来从网页上获取一些信息的。我想在一个函数中进行并行处理,这个函数负责下载网页并返回一个对象。
class WebDown:
def display(self, url):
print 'display(): ' + content
def download(self, url):
thread = Thread(target=self.get_info)
# thread join
print 'download(): ' + content
# return the info
def get_info(self, url):
# download page
# retrieve info
return info
if __name__ == '__main__':
wd = WebDown()
ret = wd.download('http://...')
wd.display('http://...')
在这个例子中,我先调用download()来获取信息,然后再调用display()来打印其他信息。打印的输出应该是
display(): foo, bar, ....
download(): blue, red, ....
2 个回答
1
在Python中,有一种写异步、不阻塞代码的方法,就是使用Python的Twisted库。Twisted不依赖于多线程,而是使用多进程。它提供了一种方便的方式来创建Deferred对象,并为这些对象添加回调和错误回调。你给出的例子在Twisted中看起来会是这样的,我使用了treq(Twisted请求)库,这让生成请求变得更快更简单:
from treq import get
from twisted.internet import reactor
class WebAsync(object):
def download(self, url):
request = get(url)
request.addCallback(self.deliver_body)
def deliver_body(self, response):
deferred = response.text()
deferred.addCallback(self.display)
return deferred
def display(self, response_body):
print response_body
reactor.stop()
if __name__ == "__main__":
web_client = WebAsync()
web_client.download("http://httpbin.org/html")
reactor.run()
这里的'download'和'deliver_body'方法都会返回一种叫做deferreds的东西,你可以给它们添加回调函数,这些函数会在结果可用时执行。