web-dev-qa-db-ja.com

ArgparseとJsonを一緒に使用する

私はPythonの初心者です。

ArgparseとJSONを一緒に使用できるかどうか知りたかったのです。たとえば、変数がありますp,q,r

私はそれらをargparseに-として追加することができます

parser.add_argument('-p','--param1',help='x variable', required=True)
parser.add_argument('-q','--param2',help='y variable', required=True)
parser.add_argument('-r','--param3',help='z variable', required=True)

ここで、JSONファイルから同じ変数を読み取りたいとしましょう。それは可能ですか?そのため、コマンドラインまたはJSONファイルから値を入力できました。

JSON入力ファイル-

{
    "testOwner": "my name",
    "tests": [
        "test1",
        "test2",
        "test3"
    ],

    "testParameters": {
        "test1": {
            "param1": "0",
            "param2": "20",
            "param3" : "True"
        },

        "test2": {
            "param1": "cc"
        }
    }   
}
10
Raj

parse_argsargs名前空間は、次のコマンドで辞書に変換できます。

argparse_dict = vars(args)

JSON値も辞書にあり、たとえばjson_dictです。選択した値を1つのディクショナリから別のディクショナリにコピーするか、スケール全体を更新できます。

argparse_dict.update(json_dict)

このようにして、json_dict値はargparse値を上書きします。

両方を保持する場合は、異なる引数(キー)名を使用するか、値をリストにする必要があります。リストは追加または拡張できます。 nargsで正しいargparse値を使用することから始めて、これにはもう少し作業が必要です。


改訂されたparserは、テスト入力を使用して生成します。

In [292]: args=parser.parse_args('-p one -q two -r three'.split())
In [293]: args
Out[293]: Namespace(param1='one', param2='two', param3='three')
In [295]: args_dict = vars(args)    
In [296]: args_dict
Out[296]: {'param1': 'one', 'param2': 'two', 'param3': 'three'}

JSON文字列を解析すると(json.loads?)、次のような辞書が生成されます。

In [317]: json_dict
Out[317]: 
{'testOwner': 'my name',
 'testParameters': {'test1': {'param1': '0', 'param2': '20', 'param3': 'True'},
  'test2': {'param1': 'cc'}},
 'tests': ['test1', 'test2', 'test3']}

ディスプレイをIpythonセッションに貼り付けて作成しましたが、JSONローダーでも同じことが作成されると思います

Argparse値は次のように追加できます。

In [318]: json_dict['testParameters']['test3']=args_dict
In [319]: json_dict
Out[319]: 
{'testOwner': 'my name',
 'testParameters': {'test1': {'param1': '0', 'param2': '20', 'param3': 'True'},
  'test2': {'param1': 'cc'},
  'test3': {'param1': 'one', 'param2': 'two', 'param3': 'three'}},
 'tests': ['test1', 'test2', 'test3']}

ここでは、それを3番目のtestセットとして追加し、(偶然に)testsリストから名前を取得しました。 json_dict['testParameters']['test2']=args_dictは、test2の値を置き換えます。

'test2'の未定義の値にargs値を追加する1つの方法は次のとおりです。

In [320]: args_dict1=args_dict.copy()    
In [322]: args_dict1.update(json_dict['testParameters']['test2'])
In [324]: json_dict['testParameters']['test2']=args_dict1
In [325]: json_dict
Out[325]: 
{'testOwner': 'my name',
 'testParameters': {'test1': {'param1': '0', 'param2': '20', 'param3': 'True'},
  'test2': {'param1': 'cc', 'param2': 'two', 'param3': 'three'},
  'test3': {'param1': 'one', 'param2': 'two', 'param3': 'three'}},
 'tests': ['test1', 'test2', 'test3']}

このバージョンのupdateを使用して、JSONディクショナリの「cc」値を優先しました。

10
hpaulj

JSONファイルに次の形式のdictが含まれているとします。

d = {"name": ["-x", "--xvar"], "help": "Help message", "required": True}

パーサーを作成した後、次のようにdictを「解凍」できます。

parser = argparse.ArgumentParser()
parser.add_argument(*(d.pop("name")), **d) 
# Put the 'name' as name/flag and then unpack the rest of
# the dict as the rest of the arguments
parser.parse_args("--xvar 12".split())
>>> Namespace(xvar='12')

ただし、これにより、メソッドの引数名に合うようにdictキーを維持する必要がありますadd_arguments。また、actiontypechoices引数を使用するような、より高度な動作を使用する単純で単純な方法もありません。

また、使用するさまざまな引数を含めるために、dictの形式を変更する必要があります。 1つの解決策は、名前/フラグをタプルのdictのキーとして持つことであり、引数はdictになります。

d = {("-x", "--xvar"): {"help": "Help message for x", "required": True}, 
     ("-y", "--yvar"): {"help": "Help message for y", "required": True}}
for names, args in d.iteritems():
    parser.add_argument(*names, **args) # Use a similar unpacking 'magic' as the first example
parser.parse_args("-x 12 --yvar 42".split())
>>> Namespace(xvar='12', yvar='42')

[〜#〜] edit [〜#〜]OPからのコメントを考えると、彼が望んでいるように見えます JSONファイルから取得したparse値。

d = {"-x": "12", "-y": "42"}
args = []
for item in d.items():
    args.extend(item)
parser.parse_args(args)
>>> Namespace(xvar='12', yvar='42')

編集2

argparseドキュメントを見る この段落 多分いくらか関連性があります。

3
bvidal