Pythonでコマンドラインパーサーのclickを使いつつasyncioを使う

当サイトではアフィリエイト広告を利用しています

PythonでClickを使ってコマンドライン引数の処理をしつつ、asyncioを使って非同期処理を行う場合にどうすればいいか手こずりました。

解決方法について記録しておきます。

利用したライブラリ

  • Python 3.11.4
  • click 8.1.3: コマンドライン引数のパーサーに利用
  • asyncio

Pythonスクリプト

from functools import wraps
import click
import asyncio

def async_cmd(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        return asyncio.run(func(*args, **kwargs))
    return wrapper

@click.command()
@click.option("-f", "--fpath", help="config file path", default="config.yml", type=click.Path(exists=True))
@async_cmd
async def main(fpath):
    pass

if __name__ == "__main__":
    main()

asyncioを使う場合はasyncio.run()を行う必要がありますが、そうするとclickでのデコレータと上手く共存できません。

なので一旦独自のデコレータを記述し、その中でasyncio.run()を使用するという段階を踏む必要があるようです。

そうして作成したデコレータをclickのデコレータと同時に利用してやればよい、ということのようでした。

私の場合はこうして呼んだasyncioの中でネットワーク通信処理を行っていました。

参考

解決には次のstackoverflowの投稿が参考になりました。