2013-11-20 7 views
21

私のargparseはトップレベルに3つのフラグ(store_true)しか持っていません。他のすべてはサブパーザルで処理されます。 myprog.py --helpを実行すると、出力には、通常の{sub1, sub2, sub3, sub4, ...}のようなすべてのサブコマンドのリストが表示されます。だから、デフォルトは素晴らしい仕事です...argparse subparserモノリシックヘルプ出力

私は通常、私が必要とする正確なサブコマンド名とそのすべてのオプションを覚えていません。だから私は2件のヘルプの検索をやって終わる:

myprog.py --help 
myprog.py sub1 --help 

私は頻繁にこれを行う、私は1つのステップにこれを詰め込むことにしました。私は、トップレベルのヘルプが巨大な要約を出力するようにしたいのですが、手動でリストをスクロールします。私はそれがはるかに高速であることがわかります(私にとっては少なくとも)。

私はRawDescriptionHelpFormatterを使用していましたが、長いヘルプ出力を手作業で入力していました。しかし、今ではサブコマンドがたくさんあり、管理するのに苦労しています。

1回のプログラム呼び出しで冗長なヘルプ出力を得る方法はありますか?

もしそうでない場合は、私のargparseインスタンスのサブパーザーを反復処理し、それぞれのヘルプ出力を個別に取り出すことができます(後で一緒に接着します)。


ここでは、私のargparse設定の簡単な概要を示します。私はこのコードをきれいに拭き取った/取り除いたので、これは少しの助けなしには動かないかもしれません。

parser = argparse.ArgumentParser(
     prog='myprog.py', 
     formatter_class=argparse.RawDescriptionHelpFormatter, 
     description=textwrap.dedent(""" You can manually type Help here """)) 

parser.add_argument('--debuglog', action='store_true', help='Verbose logging for debug purposes.') 
parser.add_argument('--ipyonexit', action='store_true', help='Drop into an embeded Ipython session instead of exiting command.') 

subparser = parser.add_subparsers() 

### --- Subparser B 
parser_b = subparser.add_parser('pdfreport', description="Used to output reports in PDF format.") 
parser_b.add_argument('type', type=str, choices=['flatlist', 'nested', 'custom'], 
         help="The type of PDF report to generate.") 
parser_b.add_argument('--of', type=str, default='', 
         help="Override the path/name of the output file.") 
parser_b.add_argument('--pagesize', type=str, choices=['letter', '3x5', '5x7'], default='letter', 
         help="Override page size in output PDF.") 
parser_b.set_defaults(func=cmd_pdf_report) 

### ---- Subparser C 
parser_c = subparser.add_parser('dbtables', description="Used to perform direct DB import/export using XLS files.") 
parser_c.add_argument('action', type=str, choices=['push', 'pull', 'append', 'update'], 
         help="The action to perform on the Database Tables.") 
parser_c.add_argument('tablename', nargs="+", 
         help="The name(s) of the DB-Table to operate on.") 
parser_c.set_defaults(func=cmd_db_tables) 

args = parser.parse_args() 
args.func(args) 
+0

いくつかのコード、ちょうど2つのオプションと2つのサブパーザーを備えた小さな例を示してください。 –

答えて

9

これは、argparseが定義されたサブパーサーのリストを直接公開しないため、ややこしいことです。しかし、それは行うことができます。

import argparse 

# create the top-level parser 
parser = argparse.ArgumentParser(prog='PROG') 
parser.add_argument('--foo', action='store_true', help='foo help') 
subparsers = parser.add_subparsers(help='sub-command help') 

# create the parser for the "a" command 
parser_a = subparsers.add_parser('a', help='a help') 
parser_a.add_argument('bar', type=int, help='bar help') 

# create the parser for the "b" command 
parser_b = subparsers.add_parser('b', help='b help') 
parser_b.add_argument('--baz', choices='XYZ', help='baz help') 
# print main help 
print(parser.format_help()) 

# retrieve subparsers from parser 
subparsers_actions = [ 
    action for action in parser._actions 
    if isinstance(action, argparse._SubParsersAction)] 
# there will probably only be one subparser_action, 
# but better save than sorry 
for subparsers_action in subparsers_actions: 
    # get all subparsers and print help 
    for choice, subparser in subparsers_action.choices.items(): 
     print("Subparser '{}'".format(choice)) 
     print(subparser.format_help()) 

この例例パーサがPython 2.7 documentation on argparse sub-commandsからあるのpython 2.7とPython 3のために働く必要があります。

残っている唯一のことは、完全なヘルプの新しい引数を追加すること、または組み込みの-h/--helpを置き換えることです。

+0

すばらしい例。これは私のために良い出力を生成しています。私の場合、-h/- help引数をどのように再定義するかはわかりません。オプションのargsはサブパーザーに従うのが好きではありません。ただし、最後に「ヘルプ」という名前の別のサブパーサーを定義するだけで、それ以前に追加されたすべての内容を検査できます。 – user2097818

2

Adaephonの例でsubparsersを反復処理するための簡単な方法は、Pythonはあなたがparser._actionsのような隠し属性にアクセスすることを可能にし

for subparser in [parser_a, parser_b]: 
    subparser.format_help() 

ですが、それはお勧めしませんです。パーサーを定義しながら独自のリストを作成するのと同じように簡単です。引数で特別なことをする場合も同じです。 add_argumentおよびadd_subparserは、それぞれActionオブジェクトとParserオブジェクトを返します。

ArgumentParserのサブクラスを作成していた場合は、_actionsを自由に使用できます。しかし、1つのアプリケーションでは、自分のリストを構築する方がより明確になります。


例:

import argparse 

parser = argparse.ArgumentParser() 
parser.add_argument('mainpos') 
parser.add_argument('--mainopt') 
sp = parser.add_subparsers() 
splist = [] # list to collect subparsers 
sp1 = sp.add_parser('cmd1') 
splist.append(sp1) 
sp1.add_argument('--sp1opt') 
sp2 = sp.add_parser('cmd2') 
splist.append(sp2) 
sp2.add_argument('--sp2opt') 

# collect and display for helps  
helps = [] 
helps.append(parser.format_help()) 
for p in splist: 
    helps.append(p.format_help()) 
print('\n'.join(helps)) 

# or to show just the usage 
helps = [] 
helps.append(parser.format_usage()) 
for p in splist: 
    helps.append(p.format_usage()) 
print(''.join(helps)) 

組み合わさ '使用' の表示は、次のとおり

usage: stack32607706.py [-h] [--mainopt MAINOPT] mainpos {cmd1,cmd2} ... 
usage: stack32607706.py mainpos cmd1 [-h] [--sp1opt SP1OPT] 
usage: stack32607706.py mainpos cmd2 [-h] [--sp2opt SP2OPT] 

組み合わせの表示が長いと冗長である助けます。これは、書式設定後、または特別なヘルプフォーマッタを使用して、さまざまな方法で編集できます。しかし、誰がそのような選択をするつもりですか?

-1

私は、ヘルプ生成時の繰り返しを簡単にするために、さまざまな参照(Parser、SubParser、StoreAction)を順番に格納する単純なラッパーをいくつか持っています。

私は現在、整理された、冗長で自動的に生成されたヘルプ出力を取得しています。私はチャンスを取ったときに概要を掲載します。

欠点が1つあります。オプションの引数に生成されたヘルプコンテンツと関係があります。それほど良くありません。これらのヘルプ出力を改善するには、ラッパー(それをきれいにしたい場合)以上のものが必要です。しかし、進化するプログラムのための良いヘルプ概要が必要な場合は、これが最も満足するはずです。ここで

8

は、カスタムヘルプハンドラ(@Adaephonの答えから、ほぼすべてのコード)との完全なsoulutionです:

import argparse 


class _HelpAction(argparse._HelpAction): 

    def __call__(self, parser, namespace, values, option_string=None): 
     parser.print_help() 

     # retrieve subparsers from parser 
     subparsers_actions = [ 
      action for action in parser._actions 
      if isinstance(action, argparse._SubParsersAction)] 
     # there will probably only be one subparser_action, 
     # but better save than sorry 
     for subparsers_action in subparsers_actions: 
      # get all subparsers and print help 
      for choice, subparser in subparsers_action.choices.items(): 
       print("Subparser '{}'".format(choice)) 
       print(subparser.format_help()) 

     parser.exit() 

# create the top-level parser 
parser = argparse.ArgumentParser(prog='PROG', add_help=False) # here we turn off default help action 

parser.add_argument('--help', action=_HelpAction, help='help for help if you need some help') # add custom help 

parser.add_argument('--foo', action='store_true', help='foo help') 
subparsers = parser.add_subparsers(help='sub-command help') 

# create the parser for the "a" command 
parser_a = subparsers.add_parser('a', help='a help') 
parser_a.add_argument('bar', type=int, help='bar help') 

# create the parser for the "b" command 
parser_b = subparsers.add_parser('b', help='b help') 
parser_b.add_argument('--baz', choices='XYZ', help='baz help') 

parsed_args = parser.parse_args() 
+1

デフォルトの 'argparse'' --help'にマッチさせるには、' parser.add_argument( '-h'、 '--help'、action = _HelpAction、help = 'ヘルプメッセージを表示して終了'オプション。 – asmeurer

0

私も_choices_actionsを使用してコマンドの簡単なヘルプを印刷することができました。

def print_help(parser): 
    print(parser.description) 
    print('\ncommands:\n') 

    # retrieve subparsers from parser 
    subparsers_actions = [ 
     action for action in parser._actions 
     if isinstance(action, argparse._SubParsersAction)] 
    # there will probably only be one subparser_action, 
    # but better save than sorry 
    for subparsers_action in subparsers_actions: 
     # get all subparsers and print help 
     for choice in subparsers_action._choices_actions: 
      print(' {:<19} {}'.format(choice.dest, choice.help)) 
関連する問題