2017-08-21 22 views
0

私はCLIを持っていますgitのようなツールに似たサブコマンド用のサブパネルを利用したビルドです。私のサブコマンドのいくつかは共通オプションを共有しているので、オプションを定義するグループパーサーがあり、それらを必要とする各サブコマンドはparents=group_parserを引数の1つとして使います。例:あなたが見るようにPython argparse親からの助けを借りて

group_parser = argparse.ArgumentParser() 
group_parser.add_argument('-f', '--foo', action='store_true') 

command1_parser = subparsers.add_parser('command1', parents=[group_parser]) 
command2_parser = subparsers.add_parser('command2', parents=[group_parser]) 

だから、Command1とcommand2の両方がオプション--fooを継承します。私がやろうとしているのは、command1とcommand2でfooのhelptextを別々に更新することです。たとえば、私がmyprog command1 -hを実行した場合、--fooの別のヘルプメッセージが表示され、myprog command2 -hを実行するとそのメッセージが表示されます。問題は、私がやるまでparse_args()は、その引数に更新するための名前空間が存在しないので、このような何かがうまくいかないです。

group_parser = argparse.ArgumentParser() 
group_parser.add_argument('-f', '--foo', action='store_true') 

command1_parser = subparsers.add_parser('command1', parents=[group_parser]) 
command1.foo['help'] = "foo help for command1" 
command2_parser = subparsers.add_parser('command2', parents=[group_parser]) 
command2.foo['help'] = "foo help for command2" 

は何とかadd_argument()の外の引数にパラメータを追加することができ、このです関数?唯一の解決策は、継承された親を使用せず、各サブコマンドごとにfooを個別に定義することですが、パラメータを更新する方法があれば理想的です。

答えて

1

アクション(引数)が作成された後にhelp(およびその他のアクション属性)を変更する方法があります。しかし、parentsメカニズムでは、別の問題があります。アクションは参照によってコピーされます。だからのhelpを変更することができても、最終的にはcommand2に変更されます。 defaultのような属性を変更しようとしているときにこれが発生しました。

私はイラストを追加し、以前のディスカッションへのリンクかもしれません。

In [2]: parent = argparse.ArgumentParser(add_help=False) 
In [4]: fooObj = parent.add_argument('--foo',default='foo1', help='foo help') 

fooObjこのadd_argumentによって作成されたアクションへの参照です。

ヘルプ属性を変更
In [5]: fooObj.default 
Out[5]: 'foo1' 
In [6]: fooObj.help  # the help parameter   
Out[6]: 'foo help' 
In [7]: parent.print_help() 
usage: ipython3 [--foo FOO] 

optional arguments: 
    --foo FOO foo help 

In [16]: cmd1._actions 
Out[16]: 
[_HelpAction(option_strings=['-h', '--help'], dest='help', nargs=0, const=None, default='==SUPPRESS==', type=None, choices=None, help='show this help message and exit', metavar=None), 
_StoreAction(option_strings=['--foo'], dest='foo', nargs=None, const=None, default='foo1', type=None, choices=None, help='new help', metavar=None)] 

In [8]: fooObj.help = 'new help' 
In [9]: parent.print_help() 
usage: ipython3 [--foo FOO] 

optional arguments: 
    --foo FOO new help 

今パーサとsubparsers

In [10]: parser = argparse.ArgumentParser() 
In [11]: sp = parser.add_subparsers() 
In [13]: cmd1 = sp.add_parser('cmd1',parents=[parent]) 
In [14]: cmd2 = sp.add_parser('cmd2',parents=[parent]) 

In [15]: cmd2.print_help() 
usage: ipython3 cmd2 [-h] [--foo FOO] 

optional arguments: 
    -h, --help show this help message and exit 
    --foo FOO new help 

_actionsはパーサのために定義された引数のリストであることを確認してください

比較2dアクションがfooObjと同じであることがわかります。 cmd2と同じです。 cmd1ためhelpを変更

In [17]: id(cmd1._actions[1]) 
Out[17]: 2885458060 
In [18]: id(fooObj) 
Out[18]: 2885458060 

ここsubparsersごとに異なるデフォルトを提供しようとする場合ですcmd2同様

In [19]: cmd1._actions[1].help = 'cmd1 foo' 
In [20]: cmd2.print_help() 
usage: ipython3 cmd2 [-h] [--foo FOO] 

optional arguments: 
    -h, --help show this help message and exit 
    --foo FOO cmd1 foo 
In [21]: fooObj.help 
Out[21]: 'cmd1 foo' 

のためにそれを変更します。

argparse - Combining parent parser, subparsers and default values

それはあるかもしれません独自のユーティリティ関数を使用して、共通引数をサブパーザに追加することをお勧めします。そうすることで、各サブパーザはActionオブジェクトを共有するのではなく、独自のコピーを持つことができます。私は理論的にはparentsのメカニズムが実際よりも良いと思う。

+0

これは非常に参考になり、他のディスカッションへのリンクに感謝します。これは明らかにその質問に答えるとともに、私にはさまざまな解決策について多くの有益な情報を与えました。親は、コマンドが文字通り同一である場合にも有効です。たとえば、--debugや各サブコマンドのすべての点でまったく同じオプションがあります。同じ名前を共有しているが、多少使い方が異なる(したがって異なるヘルプコマンドが必要な)argsについては、単にそれらを分割し、それぞれに別々の 'add_parser'行を作成しました。 – iceblueorbitz

関連する問題