2013-11-20 18 views
21

我的argparse頂層只有3個標記(store_true),其他所有內容都通過子分析器處理。當我運行myprog.py --help時,輸出顯示了像普通的所有子命令的列表,{sub1, sub2, sub3, sub4, ...}。所以,默認工作很好...argparse subparser單片幫助輸出

我通常不記得我需要的確切子命令名稱及其所有選項。所以我最終做了2個幫助查找:

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

我這樣做經常這樣做,我決定把它塞進一步。我寧願讓我的頂層幫助輸出一個巨大的總結,然後我手動滾動列表。我發現它快得多(至少對我來說)。

我正在使用RawDescriptionHelpFormatter,並且手動輸入長幫助輸出。但是現在我有很多子命令,並且成爲一個難以管理的問題。

有沒有辦法只用一個程序調用即可獲得詳細的幫助輸出?

如果不是,我該如何迭代我的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

向我們展示一些代碼的小例子,只是一些選項和幾個子分析器。 –

回答

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和python 3例子解析器是從Python 2.7 documentation on argparse sub-commands工作。

剩下的唯一要做的就是爲完整的幫助添加一個新參數,或者替換內置的-h/--help

+0

很好的例子。這對我來說產生了很好的輸出。我不知道如何在我的情況下重新定義-h/- help參數,因爲可選參數不喜歡跟隨我的子分析器。儘管我可能只是定義了另一個名爲'help'的子分析器,它可以檢查在它之前添加的所有內容。 – user2097818

2

一個簡單的迭代中Adaephon的例子中,subparsers方式是

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

Python做允許您訪問像parser._actions隱藏屬性,但是這不是鼓勵。在定義解析器的同時構建自己的列表也很容易。用這些論據做特別的事情也是一樣。出於某種原因,add_argumentadd_subparser返回其各自的ActionParser對象。

如果我正在做一個ArgumentParser的子類,我可以隨意使用_actions。但是對於一次性應用,建立我自己的列表會更清楚。


一個例子:

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),以便在生成幫助過程中輕鬆進行迭代。

我現在正在組織,詳細,自動生成幫助輸出。當我有機會時,我會發佈一個概述。

有一個缺點,這與可選參數上生成的幫助內容有關:它不是很好。改善這些幫助輸出將不僅僅是一個包裝(如果我們想保持乾淨)。但是,如果你想爲演變中的程序提供一個很好的幫助概述,這應該可以滿足大部分。

8

這裏是一個自定義幫助處理程序完成soulution(從@Adaephon答案几乎所有的代碼):

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

使用parser.add_argument('-h','--help',action = _HelpAction,help ='顯示此幫助消息並退出')'可能會更好地匹配默認的'argparse' --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))