Wait a moment...

備忘録 ーasyncioのイベントループを正常終了 with threadingー

26227
Namuyan
nem14.90xem (3)
521
0
2019-06-22 22:31:30
備忘録 ーasyncioのイベントループを正常終了 with threadingー

概要

asyncioでイベントループをぶんぶん振り回しながらthreadingモジュールを動かす事があると思う。そんな時にどうしてもイベントループを閉じれず終了できなくなる事がある、何故だろう?

 

修正前のコード

import threading
import asyncio


loop = asyncio.get_event_loop()


async def wait():
    print("into sleep")
    await asyncio.sleep(2)
    print("out sleep")


def main():
    print("start")
    future = asyncio.run_coroutine_threadsafe(wait(), loop)
    future.result(10)
    print("end")
    loop.stop()
    print("out")


if __name__ == '__main__':
    threading.Thread(target=main).start()
    loop.run_forever()
    loop.close()

このコードは動かない。

動くもののループから抜けれなくなってしまう。

 

 

正常なコード

import threading
import asyncio

loop = asyncio.get_event_loop()


async def wait():
    print("into sleep")
    await asyncio.sleep(2)
    print("out sleep")
    return 100


async def stop():
    loop.stop()


def main():
    print("start")
    future = asyncio.run_coroutine_threadsafe(wait(), loop)
    print(future.result())
    future = asyncio.run_coroutine_threadsafe(stop(), loop)

    
if __name__ == '__main__':
    threading.Thread(target=main).start()
    loop.run_forever()
    loop.close()

これは正常に終了できる。

stop()を非同期にして呼び出している。

 

結論

止め方としてはloop.stop()を実行する事が知られている。しかしメインスレッドで実行しなければならない事は知られていない(つまり非同期関数内で行う。これは例外を出さないので気付く事が出来ず穴にハマり易いと思う。

ご注意あれー

この記事を書いた人
なーむやーんならねーそうならねー♪ 備忘録を不定期連載中