私は一般的に満足しているこのコードを持っています:
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()
Choice = serversが入力のサーバー名を検証するので、必要はありません。ただし、非常に多くの有効な選択肢があると、ヘルプ出力がひどく見えます。
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
私が望むなら、どの方法をお勧めしますか:
servers
にあることの検証。ボーナス:
追加
-o
-s
オプションは上記の出力から削除され、この部分が追加されます。
server optional arguments:
Valid server names are: ApaServer, BananServer, GulServer, SolServer,
RymdServer, SkeppServer, HavsServer, PiratServer, SvartServer,
NattServer, SovServer
かなり良さそうですが、本当に-o
および-s
それ以外の場合はユーザーが知らないオプション。したがって、私はまだこのアプローチを使用しているわけではありません。
私は基本的にアーネストが言ったことを繰り返しています-選択肢のlongい長いリストを避けるために、選択ベースの引数にmetavar = ''を設定します(ただし、引数とコンマの間の空白を取り除くことはできません(例:-o ,
の代わりに -o,
)。次に、一般的な説明で利用可能な選択肢を詳細に説明できます(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
これは、元の投稿が探していたものです。
サブクラス化する必要はありません。ヘルプメッセージに表示する文字列をmetavar
引数に渡すだけです。
詳細については、 argparse documentation をご覧ください。
これと同じ問題があり、回避策として、エピローグを使用して各オプションの選択肢を説明しました。 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)
これは、元の質問のようにオプションリストが極端に長い状況では役に立ちませんが、私のように、適度に長いオプション文字列を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
サーバーベースのオプションのグループを作成するためにparser.add_argument_groupを使用し、説明argが可能な選択肢のリストを表示するようにしないのはなぜですか?次に、argparse.SUPPRESSを各オプションのヘルプに渡します。私はあなたが望むものをあなたに与えると信じています。
http://bugs.python.org/issue16468argparse only supports iterable choices
は、選択肢のフォーマットを議論するバグの問題です。選択肢のリストは、使用法ライン、ヘルプライン、エラーメッセージの3つの場所に表示できます。
パーサーが気にするのは、in
(__contains__
)テスト。ただし、書式設定、長いリスト、無制限の「リスト」(100を超える整数など)、および反復可能でない他のオブジェクトでは問題が発生します。 metavar
は、現在のユーザーがほとんどの書式設定の問題を回避する方法です(エラーメッセージが役に立たない場合があります)。自分のバージョンのargparse
を変更する方法のアイデアを得るには、問題を見てください。