2009-09-02 5 views
7

私は非同期的にウェブサイトを読んでいますが、私が知る限りurllibでは不可能です。今私は普通のソケットで読んでみましたが、HTTPは私に地獄を与えています。 私はすべての種類のファンキーなエンコーディングに遭遇しました。例えば転送コード化:チャンク化、手作業ですべての解析が必要です。asyncoreでウェブサイトを読む

URLLibのようなより良い方法はありませんか?以前はすべてが完了したときに、HTTP仕様全体を再実装するような気がしません。

現在ツイストはオプションではありません。

挨拶、

トム

答えて

5

をあなたはhttp://asynchttp.sourceforge.net/で見たことがありますか? Pythonの

『asynchttp』」モジュール 『のasyncore』とモジュール 『選択』上に構築されているモジュールのasynchatの "Pythonライブラリを論理的に拡張したものです。私たちの目標は、にあるため

「非同期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

+1

私はこの解決策が*華麗であると思う唯一の人ですか?*他のすべての非同期HTTPメソッドよりも優れているのは、実際には何かの完全非同期ソリューションです。 'get_webpage'を任意のコードに置き換え、非同期的に行うことができます。 – robru

1

私が一番遠いのは、修正されたasynchttpを使用していたことです。私はasyncore/asynchatとasynchttpの両方を使用しようとしました。私はそれの中のすべてのバグを修正しようとしました(handle_readメソッドはほぼasyncoreからコピーされ、ひどくインデントされ、チャンクエンコーディングで頭痛を与えていました)。また、asyncoreとasynchatは、私がgoogleに載せたヒントにしたがって使用するのが最善ではありません。

私はツイストで解決しましたが、それは明らかにあなたの疑問から外れています。

また、アプリケーションで何をしようとしているのか、非同期要求を望むのか、スレッドがオプションであるかどうか、GUIプログラミングを行っている場合など、それはいつも良いことです。もしそうでなければ、私は上記のスレッドバージョンに投票します。これは読みやすさとメンテナンス性を提供します。

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() 
関連する問題