2012-02-20 16 views
35

醜いヘルプの選択肢の結果の多く:私は選択肢が=のサーバーが私のために入力してサーバー名を検証することを好むPythonのargparse:私はと、一般的には満足している私はこのコードを持って出力

import argparse 

servers = [ "ApaServer", "BananServer", "GulServer", "SolServer", "RymdServer", 
      "SkeppServer", "HavsServer", "PiratServer", "SvartServer", "NattServer", "SovServer" ] 

parser = argparse.ArgumentParser(description="A program to update components on servers.") 
group = parser.add_mutually_exclusive_group() 
group.add_argument('-l', '--list', dest="update", action='store_false', default=False, help='list server components') 
group.add_argument('-u', '--updatepom', dest="update", action='store_true', help='update server components') 
parser.add_argument('-o', '--only', nargs='*', choices=servers, help='Space separated list of case sensitive server names to process') 
parser.add_argument('-s', '--skip', nargs='*', choices=servers, help='Space separated list of case sensitive server names to exclude from processing') 
args = parser.parse_args() 

ので、私はそれをする必要はありません。しかし、非常に多くの有効な選択肢を持つことはヘルプの出力はひどい見えるのです:

私がしたい場合は、推薦する方法
usage: args.py [-h] [-l | -u] 
       [-o [{ApaServer,BananServer,GulServer,SolServer,RymdServer,SkeppServer,HavsServer,PiratServer,SvartServer,NattServer,SovServer} [{ApaServer,BananServer,GulServer,SolServer,RymdServer,SkeppServer,HavsServer,PiratServer,SvartServer,NattServer,SovServer} ...]]] 
       [-s [{ApaServer,BananServer,GulServer,SolServer,RymdServer,SkeppServer,HavsServer,PiratServer,SvartServer,NattServer,SovServer} [{ApaServer,BananServer,GulServer,SolServer,RymdServer,SkeppServer,HavsServer,PiratServer,SvartServer,NattServer,SovServer} ...]]] 

A program to update components on servers. 

optional arguments: 
    -h, --help   show this help message and exit 
    -l, --list   list server components 
    -u, --updatepom  update server components 
    -o [{ApaServer,BananServer,GulServer,SolServer,RymdServer,SkeppServer,HavsServer,PiratServer,SvartServer,NattServer,SovServer} [{ApaServer,BananServer,GulServer,SolServer,RymdServer,SkeppServer,HavsServer,PiratServer,SvartServer,NattServer,SovServer} ...]], --only [{ApaServer,BananServer,GulServer,SolServer,RymdServer,SkeppServer,HavsServer,PiratServer,SvartServer,NattServer,SovServer} [{ApaServer,BananServer,GulServer,SolServer,RymdServer,SkeppServer,HavsServer,PiratServer,SvartServer,NattServer,SovServer} ...]] 
         Space separated list of case sensitive server names to 
         process 
    -s [{ApaServer,BananServer,GulServer,SolServer,RymdServer,SkeppServer,HavsServer,PiratServer,SvartServer,NattServer,SovServer} [{ApaServer,BananServer,GulServer,SolServer,RymdServer,SkeppServer,HavsServer,PiratServer,SvartServer,NattServer,SovServer} ...]], --skip [{ApaServer,BananServer,GulServer,SolServer,RymdServer,SkeppServer,HavsServer,PiratServer,SvartServer,NattServer,SovServer} [{ApaServer,BananServer,GulServer,SolServer,RymdServer,SkeppServer,HavsServer,PiratServer,SvartServer,NattServer,SovServer} ...]] 
         Space separated list of case sensitive server names to 
         exclude from processing 

  • ニース(主に)自動生成されたヘルプ出力
  • 検証することを-oまたは-sオプションに指定されたエントリはserversです。

ボーナス:

  • サーバー名の大文字小文字を区別しない文字列マッチングを持つことが可能でしょうか?追加

は私が-o-sオプションは、上記の出力から削除されmichaelfilmsの提案を使用してみましたし、この部分が追加されます。

server optional arguments: 
    Valid server names are: ApaServer, BananServer, GulServer, SolServer, 
    RymdServer, SkeppServer, HavsServer, PiratServer, SvartServer, 
    NattServer, SovServer 

を、私はそれはかなりよさそうだと思うが、私は実際に-o-sオプションについてのヘルプを提供する必要があります。だから私はまだこのアプローチを使っているわけではありません。

答えて

3

parser.add_argument_groupを使用して、サーバーベースのオプションのグループを作成し、説明argに表示される可能性のある選択肢のリストを表示させてみませんか?その後、argparse.SUPPRESSを個々のオプションのヘルプに渡します。私はそれがあなたが望むものを与えるだろうと信じています。

+0

私はそれを試してみました。しかし、私はまだこのアプローチを使用しているわけではありません。私は彼に '-o'と' -s'オプションについて知らせることによってユーザを助けなければなりません。 – Deleted

4

期待される出力を得るには、argparse.HelpFormatterをサブクラス化し、必要な書式を実装する必要があります。特に、すべての選択肢を1つの文字列にカンマで区切って入力することを担当する、独自の_metavar_formatterメソッドを実装する必要があります。

8

私はこの同じ問題を抱えていますが、回避策として、オプションの選択肢のそれぞれを記述するためにエピローグを使用しました。私はargparse.RawTextHelpFormatterを使用しなければなりませんでした。これにより、エピローグがあらかじめフォーマットされていることを指定できます。

def choicesDescriptions(): 
    return """ 
Choices supports the following: 
    choice1   - the FIRST option 
    choice2   - the SECOND option 
    ... 
    choiceN   - the Nth option 
""" 

def getChoices(): 
    return ["choice1", "choice2", ..., "choiceN"] 

parser = argparse.ArgumentParser(formatter_class=argparse.RawTextHelpFormatter, epilog=choicesDescriptions()) 
parser.add_argument(
    'choices', 
    choices=getChoices(), 
    help='Arg choice. See the choices options below' 
    ) 

args = parser.parse_args() 
print(args) 
20

何もサブクラス化する必要はありません。引数に、ヘルプメッセージに表示する文字列を渡します。

詳しくは、argparse documentationを参照してください。

37

私は基本的に、アーネストが言ったことを繰り返しています。選択肢の醜いリストを避けるために、選択肢ベースの引数に対してmetavar = ''を設定します(ただし、引数とカンマの間の空白を取り除きません利用可能な選択肢を一般的な説明で詳細に記述することができます(RawDescriptionHelpFormatterは、目立つインデントでリストされていれば便利です)。

アーネストの回答が投票された理由を理解できません。このコード

import argparse 

servers = [ "ApaServer", "BananServer", "GulServer", "SolServer", "RymdServer", 
      "SkeppServer", "HavsServer", "PiratServer", "SvartServer", "NattServer", "SovServer" ] 

parser = argparse.ArgumentParser(description="A program to update components on servers.") 
group = parser.add_mutually_exclusive_group() 
group.add_argument('-l', '--list', dest="update", action='store_false', default=False, help='list server components') 
group.add_argument('-u', '--updatepom', dest="update", action='store_true', help='update server components') 
parser.add_argument('-o', '--only', choices=servers, help='Space separated list of case sensitive server names to process. Allowed values are '+', '.join(servers), metavar='') 
parser.add_argument('-s', '--skip', choices=servers, help='Space separated list of case sensitive server names to exclude from processing. Allowed values are '+', '.join(servers), metavar='') 
args = parser.parse_args() 

これはオリジナルのポストを探していたものですうまくいけば、次のヘルプ出力

usage: run.py [-h] [-l | -u] [-o] [-s] 

A program to update components on servers. 

optional arguments: 
    -h, --help  show this help message and exit 
    -l, --list  list server components 
    -u, --updatepom update server components 
    -o , --only  Space separated list of case sensitive server names to 
        process. Allowed values are ApaServer, BananServer, 
        GulServer, SolServer, RymdServer, SkeppServer, HavsServer, 
        PiratServer, SvartServer, NattServer, SovServer 
    -s , --skip  Space separated list of case sensitive server names to 
        exclude from processing. Allowed values are ApaServer, 
        BananServer, GulServer, SolServer, RymdServer, SkeppServer, 
        HavsServer, PiratServer, SvartServer, NattServer, SovServer 

を生成します。

+0

metavarを ''に設定するかNoneに設定すると、all.move_parser.add_argument( 'old_host'、action = 'store'、choices = distinct_host、help = "古いホスト" + "、join(distinct_host) metavar = None) – user2601010

+0

'metavar = '''はエラーを引き起こしているようです。それを(引数名のような)空の文字列以外のものに設定すると、それが修正されます。 –

1

http://bugs.python.org/issue16468argparse only supports iterable choicesは、選択肢のフォーマットについて議論するバグの問題です。選択肢のリストは、使用行、ヘルプ行、およびエラー・メッセージの3つの場所に表示されます。

パーザが気にするのは、in__contains__)のテストです。しかし、フォーマットのために、長いリスト、無制限のリスト(例えば、整数> 100)、および反復可能ではない他のオブジェクトは問題を引き起こす。 metavarは、現行のユーザーがほとんどの書式設定の問題を回避できる方法です(エラーメッセージには役立たない場合があります)。問題を見て、​​の独自のバージョンを変更する方法のアイデアを入手してください。

3

これは、元の質問のようにオプションリストが極端に長い場合には役に立ちませんが、私のように、適度に長いオプション文字列を2行に分解する方法を探している人、ここに私のソリューションです:

import argparse 

class CustomFormatter(argparse.HelpFormatter): 
    """Custom formatter for setting argparse formatter_class. Identical to the 
    default formatter, except that very long option strings are split into two 
    lines. 
    """ 

    def _format_action_invocation(self, action): 
     if not action.option_strings: 
      metavar, = self._metavar_formatter(action, action.dest)(1) 
      return metavar 
     else: 
      parts = [] 
      # if the Optional doesn't take a value, format is: 
      # -s, --long 
      if action.nargs == 0: 
       parts.extend(action.option_strings) 
      # if the Optional takes a value, format is: 
      # -s ARGS, --long ARGS 
      else: 
       default = action.dest.upper() 
       args_string = self._format_args(action, default) 
       for option_string in action.option_strings: 
        parts.append('%s %s' % (option_string, args_string)) 
      if sum(len(s) for s in parts) < self._width - (len(parts) - 1) * 2: 
       return ', '.join(parts) 
      else: 
       return ',\n '.join(parts) 

このコードは、デフォルトのargparse.HelpFormatter法_format_action_invocationを上書きし、そして最後の4行を除いて、デフォルトの実装と同じです。

デフォルトのフォーマッタの挙動:

parser = argparse.ArgumentParser(description="Argparse default formatter.") 
parser.add_argument('-a', '--argument', help='not too long') 
parser.add_argument('-u', '--ugly', choices=range(20), help='looks messy') 
parser.print_help() 

出力:

usage: test.py [-h] [-a ARGUMENT] 
       [-u {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19}] 

Argparse default formatter. 

optional arguments: 
    -h, --help   show this help message and exit 
    -a ARGUMENT, --argument ARGUMENT 
         not too long 
    -u {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19}, --ugly {0,1,2,3,4,5,6, 
7,8,9,10,11,12,13,14,15,16,17,18,19} 
         looks messy 

カスタムフォーマッタの挙動:

parser = argparse.ArgumentParser(description="Argparse custom formatter.", 
           formatter_class=CustomFormatter) 
parser.add_argument('-a', '--argument', help='not too long') 
parser.add_argument('-l', '--less-ugly', choices=range(20), help='less messy') 

出力:

usage: test.py [-h] [-a ARGUMENT] 
       [-l {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19}] 

Argparse custom formatter. 

optional arguments: 
    -h, --help   show this help message and exit 
    -a ARGUMENT, --argument ARGUMENT 
         not too long 
    -l {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19}, 
    --less-ugly {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19} 
         less messy 
関連する問題