[Python]コマンドライン引数でboolを渡すときの注意点
コマンドライン引数を使う簡単なスクリプトを書くとき、引数としてTrue/Falseを渡して処理を分岐したいなんてことがあったのですが、見事にハマりました。
TL;DR
- Pythonでは、空文字(”)以外の文字列はすべてTrue判定される
- コマンドライン引数は、基本的にstr型で渡されるので、int()でキャストする必要がある
サンプルコード
引数で0 or 1を渡し、False or Trueとして処理を切り替えます。
前提として、Pythonにおいてはintとboolは以下です。
0 : False
1 : True (※正確には0以外のすべて)
# command_line_argv_sample.py import sys def main(argv): flg = bool(argv[1]) if flg: print("Do something.") else: print("Don't do anything.") if __name__ == '__main__': main(sys.argv)
実行してみると…
$ python command_line_argv_sample.py 0 Do something.
こうなります。
理由
コマンドライン引数では、値はすべてstr型で渡されるためです。
確認してみます。
... def main(argv): print(type(argv[1])) flg = bool(argv[1]) ...
$ python command_line_argv_sample.py 0 <class 'str'> Do something.
対応
intでキャストする
flg = bool(int(argv[1]))
$ python command_line_argv_sample.py 0 Don't do anything.
うまくいきました。
intでキャストする場合の補足
intはそのままTrue/False判定ができるので、実はbool()でのキャストも不要です。
import sys def main(argv): flg = int(argv[1]) if flg: print("Do something.") else: print("Don't do anything.") if __name__ == '__main__': main(sys.argv)
strtoboolを使う
True/Falseの文字列をTrue/Falseに変換する標準ライブラリがありました。
import sys from distutils.util import strtobool def main(argv): flg = strtobool(argv[1]) if flg: print("Do something.") else: print("Don't do anything.") if __name__ == '__main__': main(sys.argv)
$ python command_line_argv_sample.py False Don't do anything. $ python command_line_argv_sample.py True Do something.
こちらの方がコマンド実行する人に易しいですね。
ディスカッション
コメント一覧
まだ、コメントがありません