« ^ »

asyncioでのthreading.localの扱いを確認する

所要時間: 約 1分

Webフレームワークでのリクエストの処理の時に、リクエスト等の値をスレッドローカルな値として保持する事がある。おそらく一般的に使用されるフレームワークでは、asyncioを使う場合でも上手くやっているのだろうけれど、そもそもの挙動はどうなっているのだろうかと気になった。そこで、スレッドローカルのようでいてグローバルな変数だった場合に、それぞれのコルーチンの中からはどのように見えるのかを、簡単なasyncioのプログラムを書いて確認する事にした。

import asyncio
import threading

GLOBAL_OBJECT = None


async def work(sleep_second):
    global GLOBAL_OBJECT
    await asyncio.sleep(sleep_second)
    if GLOBAL_OBJECT is None:
        print("Update global object")
        GLOBAL_OBJECT = threading.local()
    print(GLOBAL_OBJECT)


async def main():
    await asyncio.gather(
        work(1),  # work1
        work(2),  # work2
        work(3),  # work3
    )


asyncio.run(main())
python main.py
Update global object
<_thread._local object at 0x106050d10>
<_thread._local object at 0x106050d10>
<_thread._local object at 0x106050d10>
実行

なるほど。普通にグローバル変数として不通に扱われる。まあ、それはそうだよなといった、当たり前の挙動をする事が確認できた。