web-dev-qa-db-ja.com

PEP 0492-Python 3.5asyncキーワード

PEP 0492asyncキーワードをPython 3.5に追加します。

Pythonこの演算子を使用するとどのようにメリットがありますか?コルーチンの例は次のとおりです。

async def read_data(db):
    data = await db.fetch('SELECT ...')

ドキュメントによると、これは達成します

db.fetch awaitableが完了して結果データを返すまで、read_dataコルーチンの実行を一時停止します。

このasyncキーワードには、実際には新しいスレッドの作成が含まれますか、それとも既存の予約済み非同期スレッドの使用が含まれますか?

asyncが予約済みスレッドを使用する場合、それはそれぞれ独自の単一の共有スレッドですか?

34
Paul Thompson

いいえ、コルーチンにはいかなる種類のスレッドも含まれていません。コルーチンは、cooperativeマルチタスクを可能にし、各コルーチンが自発的に制御を生成します。一方、スレッドは任意のポイントでユニットを切り替えます。

Python 3.4までは、generators;を使用して、yieldまたはyield from式を使用してコルーチンを記述できました。代わりにジェネレーターオブジェクトを作成する関数本体。コードはジェネレーターを反復処理したときにのみ実行されます。追加のイベントループライブラリ( asyncio など)と一緒に、次の信号を送るコルーチンを記述できます。彼らが忙しくなり(おそらくI/Oを待っている)、その間に別のコルーチンを実行できるというイベントループ:

import asyncio
import datetime

@asyncio.coroutine
def display_date(loop):
    end_time = loop.time() + 5.0
    while True:
        print(datetime.datetime.now())
        if (loop.time() + 1.0) >= end_time:
            break
        yield from asyncio.sleep(1)

上記のコードがyield from asyncio.sleep(1)行に進むたびに、このルーチンは次の1秒間は何も実行しないため、イベントループは別のコルーチンを自由に実行できますとにかく

ジェネレーターはコルーチンだけでなくあらゆる種類のタスクに使用でき、ジェネレーター構文を使用してコルーチンを作成すると初心者が混乱する可能性があるため、PEPはそれを実現する新しい構文を導入しますコルーチンを書いていることをより明確に

PEPを実装すると、上記のサンプルは代わりに次のように記述できます。

async def display_date(loop):
    end_time = loop.time() + 5.0
    while True:
        print(datetime.datetime.now())
        if (loop.time() + 1.0) >= end_time:
            break
        await asyncio.sleep(1)

結果のcoroutineオブジェクトには、コルーチンを駆動するためのイベントループが必要です。イベントループは、各コルーチンで順番にawaitし、何かを完了するために現在awaitしていないコルーチンを実行します。

利点は、ネイティブサポートを使用して、非同期コンテキストマネージャーとイテレーターをサポートするための追加の構文を導入できることです。コンテキストマネージャーの開始と終了、またはイテレーターのループは、コルーチン内のより多くのポイントになり、何かが再び待機しているために他のコードを代わりに実行できることを示します。

44
Martijn Pieters