2017-12-19 40 views
0

私のスクリプトにはいくつかの名前付き引数があります。私は設定ファイルやコマンドラインからそれらを提供したいと思います。いくつかの引数はデフォルトでは Python argparse設定ファイル/ dictからの必要な引数

  • 必須/必要とされている

    • これらは、引数が(設定ファイルまたはコマンドを提供されていない場合にエラーを報告しなければならない必要に応じて、コマンドライン
    • からの値でそれらをオーバーライドし、構成ファイルから
    • を読んでいます)

    以前にset_defaults()を使用していましたが、add_arguments(..., required=True)を使用するとエラーが発生します。

    Python 2.7の方が優れていますか?

    from argparse import ArgumentParser 
    
    # this dict will be read from configuration file 
    config_args = {'my_argument': 'value from configuration file'} 
    
    parser = ArgumentParser() 
    parser.add_argument('--my-argument', dest='my_argument', required=True) 
    
    # use values from configuration file by default 
    parser.set_defaults(**config_args) 
    
    # override with command line arguments when provided 
    args = parser.parse_args({}) 
    

    この例では、エラーが発生します。

    usage: [-h] --required REQUIRED 
    : error: argument --required is required 
    
  • +0

    、それは常に値を持つことになりますので、 '必要= true'には、デフォルト値とあまり意味がありません。ここで

    は、固定されたコードです。 – jordanm

    +0

    あなたは 'parser.add_argument( ' - required'、default =" test ")のように各引数にデフォルト値を追加することができます' – Stack

    +0

    'default =" some value "を使うと動作しません。ファイル。 –

    答えて

    0

    @hpaulj答えに基づいて、コードを少し調整しました。 ArgumentParserを使用して、コマンドラインまたは設定ファイルから提供されたかどうかにかかわらず、欠落している引数について通知します。

    Python27 ArgumentParserは、追加された引数アクションにアクセスするためのパブリックAPIを提供しません。しかし、プライベートプロパティ_actionsがあります。したがって、単にparser._actionsをループして、requiredプロパティをリセットすると、設定ファイルから提供されていれば十分です。

    from argparse import ArgumentParser 
    
    # this dict will be read from configuration file 
    config_args = {'my_argument': 'value from configuration file'} 
    
    parser = ArgumentParser() 
    arg = parser.add_argument('--my-argument', required=True) 
    
    # use values from configuration file by default 
    parser.set_defaults(**config_args) 
    
    # Reset `required` attribute when provided from config file 
    for action in parser._actions: 
        if action.dest in config_args: 
         action.required = False 
    
    # override with command line arguments when provided 
    args = parser.parse_args({}) 
    
    0
    In [355]: config_args = {'my_argument': 'value from configuration file'} 
    In [356]: parser = argparse.ArgumentParser() 
    

    add_argumentActionオブジェクトを作成し、返します。のは、そのオブジェクトへの参照を保存し、それを見てみましょう:そのdefaultNonestoreのデフォルトのデフォルトであることを

    In [357]: a1 = parser.add_argument('--my-argument', dest='my_argument', required 
        ...: =True) 
    In [358]: a1 
    Out[358]: _StoreAction(option_strings=['--my-argument'], dest='my_argument', nargs=None, const=None, default=None, type=None, choices=None, help=None, metavar=None) 
    

    注意してください。 requiredTrueに設定されています。

    set_defaultsa1.default値を変更:

    In [359]: parser.set_defaults(**config_args) 
    In [360]: a1 
    Out[360]: _StoreAction(option_strings=['--my-argument'], dest='my_argument', nargs=None, const=None, default='value from configuration file', type=None, choices=None, help=None, metavar=None) 
    

    set_defaultsも(subparsersためのドキュメントに示されている)の引数に表示されないdestの値を設定するために使用することができます。

    引数なしで実行すると、処理が必要なためエラーが発生します。デフォルトの存在はそれを無効にするものではありません。我々はFalseからrequired属性を変更した場合

    In [361]: parser.parse_args([]) 
    usage: ipython3 [-h] --my-argument MY_ARGUMENT 
    ipython3: error: the following arguments are required: --my-argument 
    An exception has occurred, use %tb to see the full traceback. 
    
    SystemExit: 2 
    

    a1は、その属性が、限度内で、変更することができる。すなわち、a1.default含むオ​​ブジェクトです)。

    In [362]: a1.required 
    Out[362]: True 
    In [363]: a1.required=False 
    In [364]: parser.parse_args([]) 
    Out[364]: Namespace(my_argument='value from configuration file') 
    

    設定値が表示されます。コマンドラインの値で上書きすることができます。

    またnamespaceパラメータにデフォルト値を提供することができます。

    In [365]: ns = argparse.Namespace(my_argument='foo') 
    In [366]: parser.parse_args([], namespace=ns) 
    Out[366]: Namespace(my_argument='foo') 
    

    このfoo値が優先され、そのアクションのデフォルトまたはset_defaults値が使用されていません。

    https://bugs.python.org/issue29670argparse: does not respect required args pre-populated into namespace

    このバグ/問題では、ユーザーはrequiredテストを上書きするnsに値が存在することを望んでいました。つまり、コマンドラインで値が提供されたかのように、このnsが動作するようにします。私の結論は、変更するのは簡単なことではないということです。現在のparse_args構造では、requiredのようなものの修正やバイパステストはできません。

    好きなテストをしたい場合は、default=Noneのままにしておき、解析後に独自のテストを行うことをおすすめします。

    if args.my_argument is None: 
        args.my_argument = 'default from config' 
    
    +0

    @hpauljに深い答えをありがとう!これは一般的な解決策を見つけるのに十分でした。私自身の質問に答えを加えました。 –

    関連する問題