python中的异步函数调用

时间:2014-10-26 19:51:28

标签: python multithreading

在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://...')

我这个例子,为了我打印其他信息,我在display()之后调用download()来检索信息。打印输出应为

display(): foo, bar, ....
download(): blue, red, ....

2 个答案:

答案 0 :(得分:1)

在python中编写异步,非阻塞代码的一种方法是使用Python的Twisted。 Twisted不依赖于multithreading but uses multiprocessing instead。它为您提供了创建Deferred对象的便捷方法,为它们添加了回调和错误。您提供的示例在Twisted中看起来像这样,我使用treq(Twisted Requests)库,这使得生成请求更快更容易:

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,您可以在结果可用时向其添加回调。

答案 1 :(得分:0)

我只想使用名为requestgeventgrequests

import grequests
>>> urls = [
    'http://...',
    'http://...'
]
>>> rs = (grequests.get(u) for u in urls)
>>> grequests.map(rs)
[<Response [200]>, <Response [200]>]