自作モジュールが増えてくると、コマンドライン引数の受け方が複雑になってきて、解決できないことがあるかもしれません。
この記事は、そんなときに役に立つかもしれない方法です。
argparseを便利に使う
まずは、コードです。
test.py から my_module.py を使うというものです。
# test.py import argparse parser = argparse.ArgumentParser() parser.add_argument('--mode', default='test', type=str) args = parser.parse_args() print(args) if args.mode == 'test': import my_module my_module.show_param() else: raise NotImplementedError
# my_module.py import argparse parser = argparse.ArgumentParser() parser.add_argument('--param', default='aaa', type=str) args = parser.parse_args() print(args) def show_param(): print(args.param)
これをコマンドライン引数を使わずに実行すると、こうなります。
$ python test.py Namespace(mode='test') Namespace(param='aaa') aaa
まずは、test.py にコマンドライン引数を渡してみます。
この例では、else 側に落ちて、NotImplementedError になります。
実装通りに動作しています。
$ python test.py --mode test2 Namespace(mode='test2') NotImplementedError
次に、my_module.py にコマンドライン引数を渡してみます。
$ python3 test.py --param bbb usage: test.py [-h] [--mode MODE] test.py: error: unrecognized arguments: --param bbb
test.py が –param を受けられないので、エラーになってしまいます。
これ、argparseを使っている人がまれに出くわす問題だと思います。
これの回避方法を考えてみたいと思います。
ある階層ではコマンドライン引数をスルーさせる
上記の問題は、特定のコマンドライン引数しか受け取らない仕組みがあればいいはずです。
その実装方法です。
# test2.py import argparse parser = argparse.ArgumentParser() parser.add_argument('--mode', default='test', type=str) args, unknown = parser.parse_known_args() print('args:', args) print('unknown:', unknown) if args.mode == 'test': import my_module my_module.show_param() else: raise NotImplementedError
my_module.py はそのままです。
test2.py が受け取れないコマンドライン引数である –param を渡してみます。
$ python test2.py --param bbb args: Namespace(mode='test') unknown: ['--param', 'bbb'] Namespace(param='bbb') bbb
ということで、回避方法はparse_known_args()を使う、でした。
これによって、test2.py は –param 引数があってもスルーできるのでエラーになりません。