tornado.gen
— ジェネレータベースのコルーチン¶
tornado.gen
は、ジェネレータベースのコルーチンを実装します。
注記
このモジュールにおける「デコレータとジェネレータ」のアプローチは、ネイティブコルーチン(async def
とawait
を使用)の前身であり、Python 3.5で導入されました。旧バージョンのPythonとの互換性を必要としないアプリケーションは、代わりにネイティブコルーチンを使用する必要があります。このモジュールのいくつかの部分は、ネイティブコルーチンでも依然として有用です。multi
、sleep
、WaitIterator
、with_timeout
などが特に挙げられます。これらの関数のいくつかはasyncio
モジュールにも対応するものがありますが、必ずしも100%互換性があるとは限りません。
コルーチンは、コールバックを連鎖させるよりも、非同期環境で作業する簡単な方法を提供します。コルーチンを使用するコードは技術的には非同期ですが、複数の個別の関数のコレクションではなく、単一のジェネレータとして記述されます。
例として、コルーチンベースのハンドラーを示します。
class GenAsyncHandler(RequestHandler):
@gen.coroutine
def get(self):
http_client = AsyncHTTPClient()
response = yield http_client.fetch("http://example.com")
do_something_with_response(response)
self.render("template.html")
Tornadoの非同期関数はAwaitable
またはFuture
を返します。このオブジェクトをyieldすると、その結果が返されます。
他のyield可能なオブジェクトのリストまたは辞書をyieldすることもできます。これらは同時に開始され、並列に実行されます。すべてが完了すると、結果のリストまたは辞書が返されます。
@gen.coroutine
def get(self):
http_client = AsyncHTTPClient()
response1, response2 = yield [http_client.fetch(url1),
http_client.fetch(url2)]
response_dict = yield dict(response3=http_client.fetch(url3),
response4=http_client.fetch(url4))
response3 = response_dict['response3']
response4 = response_dict['response4']
tornado.platform.twisted
がインポートされている場合、TwistedのDeferred
オブジェクトをyieldすることも可能です。このメカニズムを拡張するには、convert_yielded
関数を参照してください。
バージョン 3.2 で変更されました: 辞書サポートが追加されました。
バージョン 4.1 で変更されました: singledispatch
を介してasyncio
FuturesとTwisted Deferredsのyieldサポートが追加されました。
デコレータ¶
- tornado.gen.coroutine(func: Callable[[...], Generator[Any, Any, _T]]) Callable[[...], Future[_T]] [source]¶
- tornado.gen.coroutine(func: Callable[[...], _T]) Callable[[...], Future[_T]]
非同期ジェネレータのためのデコレータ。
旧バージョンのPythonとの互換性のために、コルーチンは特別な例外
Return(value)
を発生させることによっても「値を返す」ことができます。このデコレータが付いた関数は
Future
を返します。警告
コルーチン内で例外が発生した場合、例外情報は
Future
オブジェクトに格納されます。Future
オブジェクトの結果を検査する必要があります。そうしないと、例外がコードによって気付かれない可能性があります。これは、別のコルーチンから呼び出された場合にその関数をyieldすること、トップレベルの呼び出しにはIOLoop.run_sync
のようなものを使用すること、またはFuture
をIOLoop.add_future
に渡すことを意味します。バージョン 6.0 で変更されました:
callback
引数が削除されました。代わりに返されたawaitableオブジェクトを使用してください。
- exception tornado.gen.Return(value: Optional[Any] = None)[source]¶
coroutine
から値を返すための特別な例外。この例外が発生すると、そのvalue引数がコルーチンの結果として使用されます。
@gen.coroutine def fetch_json(url): response = yield AsyncHTTPClient().fetch(url) raise gen.Return(json_decode(response.body))
Python 3.3では、この例外は不要になりました。
return
文を直接使用して値を返すことができます(以前は、同じ関数内でyield
と値付きのreturn
を組み合わせることができませんでした)。return文との類推により、value引数はオプションですが、
raise gen.Return()
とする必要は決してありません。return
文を引数なしで使用できます。
ユーティリティ関数¶
- tornado.gen.with_timeout(timeout: Union[float, datetime.timedelta], future: Yieldable, quiet_exceptions: Union[Type[Exception], Tuple[Type[Exception], ...]] = ())[source]¶
Future
(またはその他のyield可能なオブジェクト)をタイムアウトでラップします。timeout
(IOLoop.add_timeout
で許可される形式、つまりdatetime.timedelta
またはIOLoop.time
を基準とした絶対時間)までに、入力futureが完了しない場合、tornado.util.TimeoutError
を発生させます。ラップされた
Future
がタイムアウト後に失敗した場合、quiet_exceptions
(例外型または型のシーケンス)に含まれる型であるか、asyncio.CancelledError
でない限り、その例外はログに記録されます。ラップされた
Future
はタイムアウト時にキャンセルされません。そのため、再利用できます。asyncio.wait_for
はこの関数に似ていますが、タイムアウト時にラップされたFuture
をキャンセルします。バージョン4.0の新機能。
バージョン4.1での変更:
quiet_exceptions
引数と未処理例外のログ記録が追加されました。バージョン4.4での変更:
Future
以外のyield可能なオブジェクトのサポートが追加されました。バージョン6.0.3での変更:
asyncio.CancelledError
は常に「静か」とみなされるようになりました。バージョン6.2での変更:
tornado.util.TimeoutError
はasyncio.TimeoutError
のエイリアスになりました。
- tornado.gen.sleep(duration: float) Future[None] [source]¶
指定された秒数後に解決される
Future
を返します。コルーチン内で
yield
と共に使用する場合、これはtime.sleep
(ブロッキングするため、コルーチンでは使用しないでください)のノンブロッキングなアナログです。yield gen.sleep(0.5)
この関数を単独で呼び出しても何も行われません。返された
Future
を待機する必要があります(通常はyieldすることで)。バージョン4.1の新機能。
- class tornado.gen.WaitIterator(*args: Future, **kwargs: Future)[source]¶
awaitableの結果が完了する順にyieldするイテレータを提供します。
次のようなawaitableのセットをyieldする場合
results = yield [awaitable1, awaitable2]
awaitable1
とawaitable2
の両方が返されるまでコルーチンを一時停止し、その後、両方のawaitableの結果を使用してコルーチンを再開します。いずれかのawaitableが例外を発生させると、その式はその例外を発生させ、すべての結果が失われます。可能な限り早く各awaitableの結果を取得する必要がある場合、または他のawaitableがエラーを発生させても一部のawaitableの結果が必要な場合は、
WaitIterator
を使用できます。wait_iterator = gen.WaitIterator(awaitable1, awaitable2) while not wait_iterator.done(): try: result = yield wait_iterator.next() except Exception as e: print("Error {} from {}".format(e, wait_iterator.current_future)) else: print("Result {} received from {} at {}".format( result, wait_iterator.current_future, wait_iterator.current_index))
結果は利用可能になり次第返されるため、イテレータからの出力は*入力引数と同じ順序ではありません*。現在の結果を生成したfutureを特定する必要がある場合は、属性
WaitIterator.current_future
またはWaitIterator.current_index
を使用して、入力リストからのawaitableのインデックスを取得します(WaitIterator
の構築時にキーワード引数が使用された場合、current_index
は対応するキーワードを使用します)。Python 3.5では、
WaitIterator
は非同期イテレータプロトコルを実装しているため、async for
ステートメントで使用できます(このバージョンでは、いずれかの値が例外を発生させると、反復全体が中止されますが、前の例では個々のエラーをスキップして続行できます)。async for result in gen.WaitIterator(future1, future2): print("Result {} received from {} at {}".format( result, wait_iterator.current_future, wait_iterator.current_index))
バージョン4.1の新機能。
バージョン4.3での変更: Python 3.5で
async for
サポートが追加されました。
- tornado.gen.multi(Union[List[Yieldable], Dict[Any, Yieldable]], quiet_exceptions: Union[Type[Exception], Tuple[Type[Exception], ...]] = ())[source]¶
複数の非同期操作を並列に実行します。
children
は、値がyield可能なオブジェクトであるリストまたは辞書です。multi()
は、その結果を含む並列構造に解決される新しいyield可能なオブジェクトを返します。children
がリストの場合、結果は同じ順序の結果のリストになります。辞書の場合、結果は同じキーを持つ辞書になります。つまり、
results = yield multi(list_of_futures)
は次のものと同等です。results = [] for future in list_of_futures: results.append(yield future)
いずれかのchildrenが例外を発生させると、
multi()
は最初の例外を発生させます。他のすべての例外は、quiet_exceptions
引数に含まれる型でない限り、ログに記録されます。yield
ベースのcoroutineでは、リストまたは辞書がyieldされた際にcoroutine runnerが自動的に実行するため、通常この関数を直接呼び出す必要はありません。しかし、await
ベースのcoroutineの場合、またはquiet_exceptions
引数を渡す必要がある場合は、この関数を呼び出す必要があります。この関数は、歴史的な理由から
multi()
とMulti()
という名前でも使用できます。multi()
によって返されるFuture
をキャンセルしても、その子プロセスはキャンセルされません。asyncio.gather
はmulti()
に似ていますが、子プロセスをキャンセルします。バージョン4.2での変更: 複数のyieldableが失敗した場合、最初の例外(発生した例外)以降の例外はログに記録されます。選択した例外タイプのログを抑制するための
quiet_exceptions
引数が追加されました。バージョン4.3での変更:
Multi
クラスとmulti_future
関数を、統一された関数multi
に置き換えました。YieldPoint
とFuture
以外のyieldableのサポートを追加しました。
- tornado.gen.multi_future(Union[List[Yieldable], Dict[Any, Yieldable]], quiet_exceptions: Union[Type[Exception], Tuple[Type[Exception], ...]] = ())[source]¶
複数の非同期Futureを並列に待ちます。
Tornado 6.0以降、この関数は
multi
と全く同じです。バージョン4.0の新機能。
バージョン4.2での変更: 複数の
Futures
が失敗した場合、最初の例外(発生した例外)以降の例外はログに記録されます。選択した例外タイプのログを抑制するためのquiet_exceptions
引数が追加されました。バージョン4.3で非推奨:
multi
を使用してください。
- tornado.gen.convert_yielded(yielded: Union[None, Awaitable, List[Awaitable], Dict[Any, Awaitable], Future]) Future [source]¶
yieldされたオブジェクトを
Future
に変換します。デフォルトの実装では、リスト、辞書、Futureを受け入れます。
asyncio.ensure_future
と同様に、自身で開始されていないcoroutineをすべて開始するという副作用があります。singledispatch
ライブラリが使用可能な場合、この関数を拡張して追加の型をサポートできます。例えば@convert_yielded.register(asyncio.Future) def _(asyncio_future): return tornado.platform.asyncio.to_tornado_future(asyncio_future)
バージョン4.1の新機能。
- tornado.gen.maybe_future(x: Any) Future [source]¶
x
をFuture
に変換します。x
が既にFuture
である場合は、そのまま返されます。それ以外の場合は、新しいFuture
でラップされます。これは、f()
がFuture
を返すかどうかがわからない場合に、result = yield gen.maybe_future(f())
として使用できます。バージョン4.3で非推奨: この関数は、他のyieldableオブジェクトではなく、
Futures
のみを処理します。maybe_future
の代わりに、期待する非Futureの結果型(多くの場合None
のみ)を確認し、不明なものは何でもyield
してください。
- tornado.gen.is_coroutine_function(func: Any) bool [source]¶
funcがcoroutine関数であるか、つまり
coroutine
でラップされた関数であるかどうかを返します。バージョン4.5の新機能。
- tornado.gen.moment¶
IOLoopを1回実行できるようにyieldできる特別なオブジェクトです。
通常の使用では必要ありませんが、すぐに準備できるFutureをyieldする可能性が高い、長時間実行されるcoroutineで役立つ場合があります。
使用方法:
yield gen.moment
ネイティブcoroutineでは、
yield gen.moment
に相当するものはawait asyncio.sleep(0)
です。バージョン4.0の新機能。
バージョン4.5で非推奨:
yield None
(または引数なしのyield
)は、現在yield gen.moment
と同等です。