2014-10-26 137 views
1

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

我這個例子中,爲了檢索信息,在display()中打印其他信息後調用download()。打印輸出應該是

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

你有沒有嘗試過python的線程模塊? – 2014-10-26 20:01:51

+0

是的,但我不知道如何使用線程模塊調用異步方法 – NaN 2014-10-26 20:03:42

+0

你想創建一個方法來調用異步嗎? – 2014-10-26 20:04:09

回答

0

我會簡單地使用requestgevent稱爲​​。

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

在python中編寫異步非阻塞代碼的一種方法是使用Python的Twisted。扭曲不依賴於multithreading but uses multiprocessing instead。它爲您提供了創建Deferred對象的便捷方式,爲它們添加了回調函數和errbacks。你給看起來像這樣在扭曲的例子,我用這使得生成請求再快一點treq(扭曲的要求)庫,更輕鬆:

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() 

兩個「下載」和「deliver_body」方法返回deferreds,您可以添加回調給他們,這些回調將在結果可用時執行。