109

私は、またはその両方argparseが可能な Python プログラムに使用してきました。-process-upload

parser = argparse.ArgumentParser(description='Log archiver arguments.')
parser.add_argument('-process', action='store_true')
parser.add_argument('-upload',  action='store_true')
args = parser.parse_args()

このプログラムは、少なくとも 1 つのパラメーターがなければ意味がありません。argparse少なくとも 1 つのパラメーターを強制的に選択するように構成するにはどうすればよいですか?

アップデート:

コメントに従ってください: プログラムを少なくとも 1 つのオプションでパラメータ化する Pythonic の方法は何ですか?

4

11 に答える 11

133
if not (args.process or args.upload):
    parser.error('No action requested, add -process or -upload')
于 2011-07-17T09:51:37.687 に答える
38
args = vars(parser.parse_args())
if not any(args.values()):
    parser.error('No arguments provided.')
于 2013-03-02T13:59:23.967 に答える
34

私はこれが汚れとして古いことを知っていますが、1 つのオプションを要求し、複数のオプション (XOR) を禁止する方法は次のとおりです。

parser = argparse.ArgumentParser()
group = parser.add_mutually_exclusive_group(required=True)
group.add_argument('-process', action='store_true')
group.add_argument('-upload',  action='store_true')
args = parser.parse_args()
print args

出力:

>opt.py  
usage: multiplot.py [-h] (-process | -upload)  
multiplot.py: error: one of the arguments -process -upload is required  

>opt.py -upload  
Namespace(process=False, upload=True)  

>opt.py -process  
Namespace(process=True, upload=False)  

>opt.py -upload -process  
usage: multiplot.py [-h] (-process | -upload)  
multiplot.py: error: argument -process: not allowed with argument -upload  
于 2015-10-09T22:30:52.640 に答える
20

「または両方」の部分でない場合 (最初はこれを見逃していました)、次のようなものを使用できます。

parser = argparse.ArgumentParser(description='Log archiver arguments.')
parser.add_argument('--process', action='store_const', const='process', dest='mode')
parser.add_argument('--upload',  action='store_const', const='upload', dest='mode')
args = parser.parse_args()
if not args.mode:
    parser.error("One of --process or --upload must be given")

ただし、代わりにサブコマンドを使用することをお勧めします。

于 2011-07-17T09:52:42.440 に答える
10

要件のレビュー

  • 使用しますargparse(これは無視します)
  • 1 つまたは 2 つのアクションを呼び出すことができます (少なくとも 1 つが必要です)。
  • Pythonicで試してみてください(むしろ「POSIX」ライクと呼びたいです)

コマンド ラインを使用する場合、いくつかの暗黙の要件もあります。

  • 使用方法をユーザーにわかりやすく説明する
  • オプションはオプションです
  • フラグとオプションを指定できるようにする
  • 他のパラメーター (ファイル名や名前など) との組み合わせを許可します。

docopt(ファイル)を使用したサンプル ソリューションmanagelog.py:

"""Manage logfiles
Usage:
    managelog.py [options] process -- <logfile>...
    managelog.py [options] upload -- <logfile>...
    managelog.py [options] process upload -- <logfile>...
    managelog.py -h

Options:
    -V, --verbose      Be verbose
    -U, --user <user>  Username
    -P, --pswd <pswd>  Password

Manage log file by processing and/or uploading it.
If upload requires authentication, you shall specify <user> and <password>
"""
if __name__ == "__main__":
    from docopt import docopt
    args = docopt(__doc__)
    print args

実行してみてください:

$ python managelog.py
Usage:
    managelog.py [options] process -- <logfile>...
    managelog.py [options] upload -- <logfile>...
    managelog.py [options] process upload -- <logfile>...
    managelog.py -h

ヘルプを表示:

$ python managelog.py -h
Manage logfiles
Usage:
    managelog.py [options] process -- <logfile>...
    managelog.py [options] upload -- <logfile>...
    managelog.py [options] process upload -- <logfile>...
    managelog.py -h

Options:
    -V, --verbose      Be verbose
    -U, --user <user>  Username
    -P, --pswd <pswd>  P    managelog.py [options] upload -- <logfile>...

Manage log file by processing and/or uploading it.
If upload requires authentication, you shall specify <user> and <password>

そしてそれを使用します:

$ python managelog.py -V -U user -P secret upload -- alfa.log beta.log
{'--': True,
 '--pswd': 'secret',
 '--user': 'user',
 '--verbose': True,
 '-h': False,
 '<logfile>': ['alfa.log', 'beta.log'],
 'process': False,
 'upload': True}

短い代替short.py

さらに短いバリアントが存在する可能性があります。

"""Manage logfiles
Usage:
    short.py [options] (process|upload)... -- <logfile>...
    short.py -h

Options:
    -V, --verbose      Be verbose
    -U, --user <user>  Username
    -P, --pswd <pswd>  Password

Manage log file by processing and/or uploading it.
If upload requires authentication, you shall specify <user> and <password>
"""
if __name__ == "__main__":
    from docopt import docopt
    args = docopt(__doc__)
    print args

使用法は次のようになります。

$ python short.py -V process upload  -- alfa.log beta.log
{'--': True,
 '--pswd': None,
 '--user': None,
 '--verbose': True,
 '-h': False,
 '<logfile>': ['alfa.log', 'beta.log'],
 'process': 1,
 'upload': 1}

「プロセス」および「アップロード」キーのブール値の代わりに、カウンターがあることに注意してください。

これらの単語の重複を防ぐことはできません。

$ python short.py -V process process upload  -- alfa.log beta.log
{'--': True,
 '--pswd': None,
 '--user': None,
 '--verbose': True,
 '-h': False,
 '<logfile>': ['alfa.log', 'beta.log'],
 'process': 2,
 'upload': 1}

結論

優れたコマンド ライン インターフェイスを設計することは、困難な場合があります。

コマンド ライン ベースのプログラムには複数の側面があります。

  • コマンドラインの優れた設計
  • 適切なパーサーの選択/使用

argparse多くを提供しますが、可能なシナリオを制限し、非常に複雑になる可能性があります。

docopt読みやすさを維持し、高度な柔軟性を提供しながら、物事をはるかに短くします。解析された引数を辞書から取得し、手動で (または と呼ばれる他のライブラリを使用して) 変換 (整数への変換、ファイルを開くなど) を行う場合は、コマンド ライン解析に適してschemaいることがわかります。docopt

于 2014-06-09T21:13:04.327 に答える
7

http://bugs.python.org/issue11588についてはmutually_exclusive_group、このようなケースを処理するために概念を一般化する方法を模索しています。

この開発によりargparse.pyhttps://github.com/hpaulj/argparse_issues/blob/nested/argparse.py を書くことができます:

parser = argparse.ArgumentParser(prog='PROG', 
    description='Log archiver arguments.')
group = parser.add_usage_group(kind='any', required=True,
    title='possible actions (at least one is required)')
group.add_argument('-p', '--process', action='store_true')
group.add_argument('-u', '--upload',  action='store_true')
args = parser.parse_args()
print(args)

以下を生成しますhelp

usage: PROG [-h] (-p | -u)

Log archiver arguments.

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

possible actions (at least one is required):
  -p, --process
  -u, --upload

これは、「-u」、「-up」、「--proc --up」などの入力を受け入れます。

https://stackoverflow.com/a/6723066/901925のようなテストを実行することになりますが、エラー メッセージはより明確にする必要があります。

usage: PROG [-h] (-p | -u)
PROG: error: some of the arguments process upload is required

私は疑問に思う:

  • パラメータはkind='any', required=True十分に明確ですか (グループのいずれかを受け入れます。少なくとも 1 つが必要です)。

  • 使用法は(-p | -u)明確ですか?必須の相互排他的グループは、同じことを生成します。代替表記はありますか?

  • phihag'sこのようなグループを使用することは、単純なテストよりも直感的ですか?

于 2014-06-10T20:42:06.757 に答える
5

少なくとも 1 つのパラメーターを使用して python プログラムを実行する必要がある場合は、オプションの接頭辞 (デフォルトでは - または --)を持たないnargs=+引数を追加し、設定します (少なくとも 1つの引数が必要です)。私が見つけたこの方法の問題は、引数を指定しないと、argparse が「引数が少なすぎます」というエラーを生成し、ヘルプ メニューを出力しないことです。その機能が必要ない場合は、コードで行う方法を次に示します。

import argparse

parser = argparse.ArgumentParser(description='Your program description')
parser.add_argument('command', nargs="+", help='describe what a command is')
args = parser.parse_args()

オプションのプレフィックスを使用して引数を追加すると、オプションだけでなく、引数パーサー全体が nargs によって制御されると思います。(私が言いたいのは、--optionフラグがの場合nargs="+"--optionフラグは少なくとも 1 つの引数を期待optionするnargs="+"ということです。

于 2013-07-20T00:12:21.837 に答える
4

これは目的を達成し、これはargparseの自動生成された--help出力にも反映されます。これは、ほとんどの正気なプログラマーが望んでいるものです(オプションの引数でも機能します)。

parser.add_argument(
    'commands',
    nargs='+',                      # require at least 1
    choices=['process', 'upload'],  # restrict the choice
    help='commands to execute'
)

これに関する公式ドキュメント: https://docs.python.org/3/library/argparse.html#choices

于 2019-07-13T10:50:15.177 に答える