[Python]Python非同期プログラミング


今回RedisとFastapiでapiを開発する際には非同期を学ぶ必要があると思います.

同期と非同期


関数が完了するかどうかに関心があるかどうか
同期(Synchronous)
  • は、現在のタスクの応答結果を受信すると、次のタスクを順次要求する.
  • ジョブの結果の確認を続行します.
  • 非同期
  • は、現在のタスクの応答結果を受信する前に、次のタスクを要求する.
  • 作業の結果を確認しない.
  • 下図を見ると分かりやすいです.

    📂 Image Source-toolsqa

    ブロックと非ブロック


    関数の戻り点と制御権を渡すかどうか
    ブロッキング
  • の制御権を持つ関数が関数を呼び出し、関数に渡すと、関数の完了を待つのではなく、制御権が待機します.
  • ノンブロッキング
  • の制御権を有する関数が関数を呼び出すと、その関数の戻り結果が得られ、制御権が既存の制御権を有する関数である場合、他の操作が可能である場合.
  • 非同期と非ブロックは混同しやすい.ブロックI/Oが使用されているが,プログラムの実行を個別のチャネルで阻止することなく,非同期開発といえる.つまり、blockは主にI/Oについて話しています.asyncはプログラミング方法です.この4つはそれぞれ組み合わせて、それぞれ4つの異なる方法でプログラミングすることができます.

    Coroutine


    コルディンはcooperative routineの略で、互いに協力するルディンを意味する.非コルディン関数はmain routinesub routineからなり,それらは互いに依存している.次のコードでは,calc関数がmainルーチン,add,mul関数がそれぞれsubルーチンとなり,タスク終了時にcalc関数を返す.
    def add(a, b):
        c = a + b 
        return c
        
    def mul(a, b):
    	c = a * b
        return c
    	
    def calc():
        add = add(1, 2)    # add 함수가 끝나면 다시 calc 함수로 돌아옴
     	mul = mul(2, 3)    # mul 함수가 끝나면 다시 calc 함수로 돌아옴
        print(add, mul)
        
        
    calc()
    ただし、coroutineは従属関係ではなく対等関係であり、mainルーチンの最初の呼び出しがある場合、coroutineはそのタスクを実行し、職業がまだ完了していない場合でも、mainルーチンに戻って次のタスクを実行する.これらpythonのcoroutineは、単一スレッドの待ち時間を短縮し、CPUを最大限に利用することができる.

    asyncio


    📂 Asyncio Documentation
    asyncioはPython同期コードを記述するライブラリです.asyncioは、以下に示すようにasync文およびawait文で簡単に使用できます.
    import asyncio
    
    async def func():
    	await asyncio.sleep(1)
        print('foo foo')
    
    asyncio.run(func())
    
    asyncio関数を使用する場合は、上記で定義したfunc関数の実行が完了する前に、他のコードを実行できます.

    uvloop


    よくasyncioとパートナーになるuvloopはasyncioのアクティブループの代替品です.Cython(python関数を使用してC言語を呼び出す)実装により、asyncioをより迅速に作成できます.このuvloopがどれほどよくできているかによって、asyncioの性能を効果的に向上させることができるため、Python非同期プログラミングにおいて核心的な役割を果たしています.
    イベントループ(Event Loop)
    イベントループはloopのように、繰り返しの文でタスクを1つずつ実行します.タスクが完了していなくても、Event Loopに制御権が渡されるため、Event Loopは次のタスクを実行します.
    リファレンス
    🔗 PyCon.KR 2019|Pythonを使用してサーバーを極限まで引き延ばす:Async I/Oの底-一石
    🔗 Blocking-NonBlocking-Synchronous-Asynchronous
    🔗 日立開発ブログ|Python:asyncioより高速uvloop
    🔗 エンコードスタンプ|サブルーチンに値を送信