5

webapp 内でTwisted のノンブロッキング getPageメソッドを使いたいのですが、urlopen と比べるとかなり複雑に感じます。

これは私が達成しようとしているものの例です:

def web_request(request):
   response = urllib.urlopen('http://www.example.org')
   return HttpResponse(len(response.read()))

getPage で似たようなものを作るのは難しいですか?

4

2 に答える 2

20

ノンブロッキング操作 (明示的に望んでいると思われる操作) について理解しておくべきことは、それらを使用してシーケンシャル コードを実際に記述できないことです。結果を待たないため、操作はブロックされません。これらは操作を開始し、制御を関数に返します。そのため、getPage読み取り可能なファイルのようなオブジェクトは返されませんurllib.urlopen。そして、それがあったとしても、データが利用可能になるまでそれから読み取ることができませんでした (またはブロックされます)。そのためlen()、最初にすべてのデータを読み取る必要があるため(ブロックされます)、それを呼び出すことはできません。

Twisted で非ブロッキング操作を処理する方法はDeferreds、コールバックを管理するためのオブジェクトである を使用することです。getPageを返しますDeferred。これは、「後でこの結果を得る」ことを意味します。結果を取得するまでは、結果に対して何もできないため、 にコールバックを追加するDeferredと、は結果Deferred利用可能になるとこれらのコールバックを呼び出します。そのコールバックは、あなたが望むことを行うことができます:

def web_request(request)
    def callback(data):
        HttpResponse(len(data))
    d = getPage("http://www.example.org")
    d.addCallback(callback)
    return d

あなたの例の追加の問題は、web_request関数自体がブロックされていることです。の結果が利用可能になるのを待っている間に何をしたいgetPageですか? 内で何か他のことをしますweb_requestか、それともただ待ちますか? それとも、自分web_request自身をノンブロッキングにしますか? もしそうなら、どのように結果を出したいですか?(Twisted での明らかな選択は、別のものを返すことです。Deferredまたは、上記の例のように、returns と同じものをgetPage返すことです。ただし、別のフレームワークでコードを書いている場合、これは常に適切であるとは限りません。)

を使用してシーケンシャル コードを記述する方法がありますDeferreds、多少制限があり、デバッグが難しく、コアの Twisted の人々はそれを使用すると泣きます: twisted.internet.defer.inlineCallbacks. Python 2.5 の新しいジェネレーター機能を使用して、データをジェネレーターに送信できます。コードは次のようになります。

@defer.inlineCallbacks
def web_request(request)
    data = yield getPage("http://www.example.org")
    HttpResponse(len(data))

明示的にdDeferred を返した例のように、これは呼び出し元web_requestがノンブロッキングであることを期待している場合にのみ機能します。defer.inlineCallbacksデコレーターはジェネレーターを を返す関数に変えますDeferred

于 2010-04-27T11:53:32.057 に答える
4

を使用して URL からコンテンツを取得するために必要な最小限のコードを提供する同様の質問への回答を最近投稿しました。完全を期すために以下に示します。getPage

from twisted.web.client import getPage
from twisted.internet import reactor

url = 'http://aol.com'

def print_and_stop(output):
    print output
    if reactor.running:
       reactor.stop()

if __name__ == '__main__':
    print 'fetching', url
    d = getPage(url)
    d.addCallback(print_and_stop)
    reactor.run()

おそらく、Twisted がイベントを処理するために使用するリアクター パターンをより深く理解する必要があることに注意してください(getPageこの場合、発火はイベントです)。

于 2010-04-27T16:47:39.507 に答える