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と同等です。