辞書ライクなPythonコマンドライン引数の取扱
Table of Contents
2020年12月31日編集: この方法は bash では有効ですが,Windowsコマンドプロンプト ではエラーとなりました.コマンドライン引数の処理方法が異なるためのようです.Windows コマンドプロンプトへの対応を最後に追記しました.
bashの場合
Pythonのコマンドライン引数で辞書ライクな文字列を読み込み,あらかじめ用意していた辞書のデフォルト値を書き換える方法です.こうすることで関数の引数の扱いが簡単になります.JSONを用います.以下のようなコマンドライン引数を想定します.これは辞書をアポストロフィで囲んで1つの文字列にした形をしています.
python test.py '{"start": "2004-1-10", "end": "2004-8-31"}'
デフォルト値を設定した辞書を作っておき,コマンドライン引数を用いてその辞書の値の一部を変更することを考えます.
import sys
import json
### 辞書argvsの形式とデフォルト値を設定しておきます
### キーに対応する値は適当なデフォルト値を設定
friver_dir = "../dat"
river = "default_river"
stn = "defalt_stn"
start = "2020-12-01"
end = "2020-12-31"
### デフォルト値を持つ辞書を作っておきます
argvs = {"friver_dir":friver_dir, "river":river, "stn":stn, \
"start":start, "end":end}
if len(sys.argv) > 1: # コマンドライン引数が存在すれば
### jsonを用いて辞書ライクなコマンドライン引数を辞書に変換する
argvs_cmd = json.loads(sys.argv[1]) # sys.argv[0]はスクリプト名です
for key in argvs_cmd.keys(): # コマンドライン引数のkeyに関するループ
if key in argvs: # コマンドライン引数の辞書ライクなkeyが辞書に存在したら
argvs[key] = argvs_cmd[key] # 辞書のデフォルト値を書き換える
else: # コマンドライン引数が存在しなければデフォルト値をそのまま使います
print("No command line argument")
print(argvs)
JSONではdatetimeが直接扱えないので,このようにするのが簡単です.
Windowsコマンドプロンプトへの対応(bash でも可)
Windowsコマンドプロンプトではコマンドライン引数中のクオーテーションが解釈されず,スペースは必ず引数の区切りと判断されるようです.そこで,コマンドライン引数をそれぞれ key 値
の順にスペース区切りで並べ(クオーテーションは付けません),辞書に変換して扱います(bash でも可).
以下のようにコマンドライン引数を与えて実行することを想定します.
python test.py start 2004-1-10 end 2004-8-31
コードは以下のようにします.
import sys
### 辞書argvsの形式とデフォルト値を設定しておきます
### キーに対応する値は適当なデフォルト値を設定
friver_dir = "../dat"
river = "default_river"
stn = "defalt_stn"
start = "2020-12-01"
end = "2020-12-31"
### デフォルト値を持つ辞書を作っておきます
argvs = {"friver_dir":friver_dir, "river":river, "stn":stn, "start":start, "end":end}
if len(sys.argv) > 1: # コマンドライン引数が存在すれば
args_list = sys.argv[1:] # ":"が重要.リスト作成
keys = args_list[0::2] # 偶数インデックスをkeyに
vals = args_list[1::2] # 奇数インデックスを値に
argvs_cmd = dict(zip(keys, vals)) # コマンドライン引数辞書の作成
for key in argvs_cmd.keys(): # コマンドライン引数辞書のkeyのループ
if key in argvs: # keyが元の辞書に存在したら
argvs[key] = argvs_cmd[key] # 辞書のデフォルト値を書き換える
else: # コマンドライン引数が存在しなければ
print("No command line argument")
print(argvs)