Python の Async for ループ

Abdul Mateen 2023年10月10日
  1. Python の非同期関数
  2. Python の非同期 for ループ
Python の Async for ループ

このチュートリアルでは、Python の非同期 for ループについて詳しく説明します。 非同期関数、非同期 for ループ、および sleep の概念について説明します。

次に、Python ライブラリ asyncio と非同期コードを実行するために必要な関数について説明します。 最後に、概念を完全に理解するために、Python でいくつかの例を見ていきます。

Python の非同期関数

非同期関数は、同じプログラムの他の関数と並行して重いタスク (バッチ プログラムなど、バックグラウンドでプロセスを実行することに関心があるかもしれません) を実行するのに役立ちます。 関数が相互に依存していないか、相互に完全に依存していない場合、関数を並列に実行できます。

同期関数はタスクが完了すると制御を返しますが、非同期関数は制御を返し、他の関数/コードを並行して実行し、しばらくしてから制御を取り戻します。 このように、重いタスクを完了するだけでなく、他の多くのタスクも並行して完了します。

技術的には、同期関数は main 関数の制御をブロックしますが、非同期関数は main 関数をブロックせずに実行します。 このようにして、main 関数は複数の非同期関数を並行して実行できます。

Python の非同期 for ループ

同期ループの場合、一時停止/制御を与えることなく実行されます。 ただし、それらを非同期にするには、非同期関数でそれらを定義する必要があります。 また、他の機能を制御するために、このプロセスで一定期間スリープする必要があります。

sleep ステートメントを使用する

プロセス/スレッド/関数がしばらくスリープ状態になることがあります。 あなたはそれを休憩と考えるかもしれません。 ただし、その目的は、一定期間制御を失うことです。

その結果、他の関数が制御を取得します。 しばらくすると、制御が元に戻り、機能が再開されます。

いよいよ、Python での実装に移ります。 構文部分について順を追って説明し、最後に完全なコードを示します。

Python ライブラリと関数

asyncio は、async/await 構文を使用して並行プログラム/関数を作成するための Python のライブラリです。 async は、すべての関数の開始時に (非同期関数を作成するために) 使用されるキーワードです。

構文は次のとおりです。

async def fun_a(t):

ここで async を追加して、この関数を非同期関数として宣言しています。

sleep 関数は、コルーチンの実行を一定期間中断することができます。 コルーチンは、実行中にパイプライン構造を作成するプロセス/関数です。

この関数は、await キーワードを使用して、CPU を自発的に別の協調タスクに任せます。 sleep 関数の構文は次のとおりです。

await asyncio.sleep(1)

注意: キーワード await は、すべての非同期関数を呼び出すために必要です。これは、ライブラリまたはユーザー定義関数からのものです。

await キーワードは、制御をイベント ループに戻します。 非同期関数が await コマンドで呼び出された場合、sleep ステートメント (for ループ内) が、スリープ状態になるまで協調プロセスを制御すると考えることができます。

gather 関数は、複数の協調プロセス (技術的にはコルーチンを作成する) を組み合わせて、1つのユニットとして実行します。 この関数は、gather 呼び出しで記述された関数の順序で結果のタプルを返します。

構文は次のとおりです。

results = await asyncio.gather(fun_a(5), fun_b(5))

ここでは、fun_afun_b を同時に実行できるようにパイプラインを作成しています。

イベント ループは、すべての非同期アプリケーションの主要な構成要素です。 イベント ループは非同期関数を実行します。

get_event_loop() メソッドは、set_event_loop がまだ呼び出されていないかどうかを確認し、イベント ループを作成して現在のループとして設定します。 構文は次のとおりです。

my_loop = asyncio.get_event_loop()

ループがすでに作成されているときにこのコマンドを 2 回実行しても、何も実行されません。 ただし、最初の呼び出しではループは作成されません。 したがって、非同期ループが作成されます。

run_until_complete() は、get_event_loop() によって返されるループが非同期の場合、イベント ループを同時に実行するために使用されます。 構文は次のとおりです。

my_loop.run_until_complete(main())

main 関数が非同期の場合、このステートメントはコードを同時に実行します。

非同期コード

非同期関数/ルーチン/プロセスを実行するために必要な概念と Python ライブラリについて明確な考えを持っているので、完全なコーディング例を見てみましょう。

import asyncio


async def fun_a(t):
    for i in range(t):
        print("fun_a", end=" ")
        await asyncio.sleep(1)
    return 1


async def fun_b(t):
    for i in range(t):
        print("fun_b", end=" ")
        await asyncio.sleep(1)
    return 2


async def main():
    results = await asyncio.gather(fun_a(5), fun_b(5))
    print(results)


my_loop = asyncio.get_event_loop()
my_loop.run_until_complete(main())

このコードの一番上 (一番最初の行) で、asyncio ライブラリをインポートしています。 このライブラリには、非同期関数を呼び出して同時に実行するために必要な関数があります。 それらはすでに構文で説明されています。

次に、同時に実行したい 2つの非同期関数 fun_afun_b があります。 ここでも、メイン関数から非同期関数を呼び出したいと考えています。 したがって、メインも非同期関数として作成されます。

また、5 を関数に渡して、その内部でループを 5 回実行していることにも注意してください。 そのため、後で出力を確認して、ループが完全に実行されていないことに気付くことができます。 それぞれがスリープ状態になり、他の機能に制御を渡します。

出力後にこの点を繰り返します。

main 関数内で gather 関数を呼び出し、非同期関数を渡して並列実行できるようにしました。 gather 関数は、ターゲットの非同期関数から返された 2つの値を持つタプルを返します。

いよいよ最後の2行に突入です。 最後から 2 行目で、get_event_loop 関数を呼び出してループを作成しました。 最後の行では、ループを使用して、run_until_complete 関数を呼び出して、main 関数の非同期実行を開始しました。

このコードの出力は次のとおりです。

fun_a fun_b fun_a fun_b fun_a fun_b fun_a fun_b fun_a fun_b [1, 2]

まず、ループが従来のコードのように完全に実行されていないことに注意してください。 代わりに、両方のループが同時に実行されます。 両方の関数 print ステートメントの結果を確認できます。

最後に、[1, 2] は非同期関数から main 関数が受け取ったタプルです。 12 は非同期関数によって返され、gather 関数でこれらの関数を記述した順序で配置されます。

関連記事 - Python Loop