4

Python optparse では、通常、ユーザーがオプションを複数回指定することを許可し、最後のオプション以外のすべてのオプションを黙って無視します。たとえば、オプションのアクション--foostoreで、オプションのアクション--flagstore_conststore_trueまたはstore_falseの場合、次のコマンドは同等になります。

my-command --foo=bar --foo=another --flag --foo=last --flag
my-command --flag --foo=last

(更新: argparse はデフォルトで同じことを行います。)

現在、私には多くのオプションがあり、それらのいずれかを複数回指定しても意味がありません。ユーザーが同じオプションを複数回指定した場合、エラーの可能性について警告したいと思います。

複数回指定されたオプションを検出する最もエレガントな方法は何ですか? 同じオプションに、短い形式、長い形式、省略された長い形式を含めることができることに注意してください (したがって、-f--foobar--foobおよび--fooはすべて同じオプションです)。同じデスティネーションを持つ複数のオプションが同時に指定された場合を検出できればさらに良いでしょう。ユーザーが両方--quietを指定した場合に警告を発し、--verbose両方のオプションが同じデスティネーションに値を格納し、効果的に実行できるようにします。互いにオーバーライドします。

更新: よりユーザーフレンドリーにするために、警告はコマンドラインで使用される正確なオプション名を参照する必要があります。appendの代わりにアクションを使用することstoreは可能ですが、競合を検出した場合、どのオプションがそれを引き起こしたかを判断できません ( -qand--verboseまたは--quiet --quiet?)。

残念ながら、私は optparse に固執しており、Python 2.6 をサポートする必要があるため、argparse を使用できません。

PSargparseでのみ機能するソリューションを知っている場合は、それも投稿してください。外部依存関係の数を最小限に抑えようとしていますが、Python 2.6 で argparse を使用することはまだオプションです。

4

2 に答える 2

1

正しい方法は、何らかの方法で「自分の行動を定義する」ことだと思います。

たとえば、アクションを使用してcallback、目的の動作を実装する関数を実装できます。宛先がすでに入力されているかどうかを最初にチェックする関数を作成できます。入力されている場合は、重複するオプションをリストに保存します。解析が終了したら、これらのリストが空かどうかを確認し、空でない場合は適切な例外を発生させる必要があります。

これを行う別の方法は、独自のアクションを定義することです。ここで見ることができます

コールバックを使用する小さな例:

import sys
import functools
from optparse import OptionParser


bad_option = 'BAD OPTION'

def store(option, opt, value, parser, dest, val):
    """Set option's destination *dest* to *val*  if there are no conflicting options."""
    list_name = dest + '_options_list'
    try:
        # if this option is a conflict, save its name and set the value to bad_option
        getattr(parser.values, list_name).append(opt)
        setattr(parser.values, dest, bad_option)
    except AttributeError:
        # no conflicts, set the option value and add the options list
        setattr(parser.values, dest, val)
        setattr(parser.values, list_name, [opt])

store_true = functools.partial(store, val=True)
store_false = functools.partial(store, val=False)


parser = OptionParser()
parser.add_option('-v', '--verbose',
                  action='callback', callback=store_true,
                  help='Increase output verbosity',
                  callback_kwargs={'dest': 'verbose'})

parser.add_option('-q', '--quiet',
                  action='callback', callback=store_false,
                  help='Decrease output verbosity',
                  callback_kwargs={'dest': 'verbose'})

opts, args = parser.parse_args()

# detects all conflicting options for all destinations
found = False
for dest in ('verbose',):
    if getattr(opts, dest) == bad_option:
        conflicting_opts = ', '.join(getattr(opts, dest + '_options_list'))
        print('Conflicting options %s for destination %s'
              % (conflicting_opts, dest))
        found = True

if found:
    parser.print_usage()
    sys.exit(2)

そして出力:

$ python testing_optparse.py -v -q
Conflicting options -v, -q for destination verbose
Usage: prova_optparse.py [options]

おそらく、OptionValueError競合を検出するときに を発生させた方がよいでしょう。競合するすべてのオプションを取得したい場合は、残りの引数を解析する必要があります( in parser.rargs)。

于 2012-09-17T18:11:57.647 に答える
1

action="append"( ) を使用optparseして、追加された要素の数を確認できます。http://docs.python.org/library/optparse.html#other-actionsを参照してください

于 2012-09-17T14:30:09.667 に答える