2009-09-02 20 views
7

我想讀取一個網站異步,這是不可能的,據我所知urllib。現在我試着用簡單的套接字來閱讀,但是HTTP給了我一個地獄。 我遇到了各種各樣的時髦編碼,例如傳輸編碼:分塊,必須手動解析所有的東西,我覺得現在編碼C,而不是Python。用asyncore讀取一個網站

是不是有一個更好的方式,像URLLib,異步?我真的不想重新實現整個HTTP規範,當它完成之前就完成了。

當前扭曲的選項。

問候,

湯姆

回答

5

你看着http://asynchttp.sourceforge.net/?爲Python

的「asynchttp」模塊是Python庫‘asynchat’模塊,它是建立在‘asyncore’和‘選擇’模塊的邏輯延伸。我們的目標是

「異步HTTP客戶端在不使用阻塞套接字的情況下提供出色的'httplib'模塊的功能。「

該項目的最後一次提交是2001-05-29,因此它看起來死了。但無論如何它可能是有趣的。

聲明:我自己沒有用過。

另外,this blog post有一些關於異步HTTP的信息。

7

可以實現異步調用自己。對於每個調用,啓動一個新線程(或嘗試從一個池中獲取一個線程)並使用回調來處理它。

你可以用一個裝飾做到這一點非常漂亮:

def threaded(callback=lambda *args, **kwargs: None, daemonic=False): 
    """Decorate a function to run in its own thread and report the result 
    by calling callback with it.""" 
    def innerDecorator(func): 
     def inner(*args, **kwargs): 
      target = lambda: callback(func(*args, **kwargs)) 
      t = threading.Thread(target=target) 
      t.setDaemon(daemonic) 
      t.start() 
     return inner 
    return innerDecorator 

@threaded() 
def get_webpage(url): 
    data = urllib.urlopen(url).read() 
    print data 
+2

對不起,我說,我要異步插座,而不是線程。 – Tom 2009-09-02 13:09:33

+1

我是唯一認爲這個解決方案*輝煌*的人嗎?比所有其他異步HTTP方法更好的是它實際上是一個完全通用的異步解決方案,用於* anything *。你可以用你想要的任何代碼替換'get_webpage',並讓它異步發生。 – robru 2012-08-31 23:43:25

1

我來的最遠的地方是使用修改後的asynchttp,codeape建議。我曾嘗試使用asyncore/asynchat和asynchttp,並帶來很多痛苦。我花了太多的時間來嘗試修復所有的錯誤(有一個方法handle_read,幾乎從asyncore複製,只是嚴重縮進,並給我頭痛的分塊編碼)。此外,asyncore和asynchat最好不要根據我在谷歌上提供的一些提示來使用。

我已經解決了扭曲,但這顯然不適合你。

它也可能取決於什麼是你想與你的應用程序,你爲什麼要異步請求,如果線程是一種選擇或沒有,如果你正在做的GUI編程或別的東西,所以如果你能提供一些線索更inforation ,這總是很好。如果沒有,我會投票支持上面提到的線程版本,它提供了更多的可讀性和可維護性。

1

Asyncore簡單的HTTP客戶端的例子是非常簡單:)

http://docs.python.org/library/asyncore.html

import asyncore, socket 

class HTTPClient(asyncore.dispatcher): 

    def __init__(self, host, path): 
     asyncore.dispatcher.__init__(self) 
     self.create_socket(socket.AF_INET, socket.SOCK_STREAM) 
     self.connect((host, 80)) 
     self.buffer = 'GET %s HTTP/1.0\r\n\r\n' % path 

    def handle_connect(self): 
     pass 

    def handle_close(self): 
     self.close() 

    def handle_read(self): 
     print self.recv(8192) 

    def writable(self): 
     return (len(self.buffer) > 0) 

    def handle_write(self): 
     sent = self.send(self.buffer) 
     self.buffer = self.buffer[sent:] 


client = HTTPClient('www.python.org', '/') 
asyncore.loop()