ノンブロッキング操作 (明示的に望んでいると思われる操作) について理解しておくべきことは、それらを使用してシーケンシャル コードを実際に記述できないことです。結果を待たないため、操作はブロックされません。これらは操作を開始し、制御を関数に返します。そのため、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))
明示的にd
Deferred を返した例のように、これは呼び出し元web_request
がノンブロッキングであることを期待している場合にのみ機能します。defer.inlineCallbacks
デコレーターはジェネレーターを を返す関数に変えますDeferred
。