5

イベント データをカスタム スクリプトに送信できるアプリケーションがあります。コマンド ライン引数を並べて、どのイベント データがどの引数に対応するかを割り当てるだけです。問題は、ここには真の柔軟性がないことです。計画したすべてのオプションが使用されますが、すべてのオプションに必ずしもデータがあるわけではありません。そのため、アプリケーションがスクリプトに送信する文字列を作成すると、一部の引数が空白になり、python の OptionParser が「エラー: --someargument オプションには引数が必要です」というエラーが発生します。

200 を超えるデータ ポイントがあるため、可能な引数の各組み合わせを処理するために個別のスクリプトを作成できるわけではありません (2^200 スクリプトが必要です)。Pythonのoptionparserで空の引数を処理する方法はありますか?

4

6 に答える 6

10

申し訳ありませんが、私の最初の答えで質問を誤解しました。オプションを定義するときに、コマンドラインフラグにコールバックアクションタイプを使用するオプションの引数を設定する機能を実現できます。次の関数をコールバックとして使用し(ニーズに合わせて調整することをお勧めします)、オプションで引数を受け取ることができるフラグごとに関数を構成します。

import optparse

def optional_arg(arg_default):
    def func(option,opt_str,value,parser):
        if parser.rargs and not parser.rargs[0].startswith('-'):
            val=parser.rargs[0]
            parser.rargs.pop(0)
        else:
            val=arg_default
        setattr(parser.values,option.dest,val)
    return func

def main(args):
    parser=optparse.OptionParser()
    parser.add_option('--foo',action='callback',callback=optional_arg('empty'),dest='foo')
    parser.add_option('--file',action='store_true',default=False)
    return parser.parse_args(args)

if __name__=='__main__':
    import sys
    print main(sys.argv)



コマンドラインから実行すると、次のように表示されます。

# python parser.py
(<Values at 0x8e42d8: {'foo': None, 'file': False}>, [])

# python parser.py --foo
(<Values at 0x8e42d8: {'foo': 'empty', 'file': False}>, [])

# python parser.py --foo bar
(<Values at 0x8e42d8: {'foo': 'bar', 'file': False}>, [])
于 2009-08-04T20:11:30.700 に答える
1

私はこれができないと思いますoptparse。オプションにオプションの値があるこのような状況を処理argparseできる別の(非標準)モジュールです。

optparse値を含むオプションを指定するか、両方を除外する必要があります。

于 2009-08-04T19:17:40.403 に答える
1

はい、オプションを追加するときにそうする引数があります。

from optparse import OptionParser
parser = OptionParser()
parser.add_option("--SomeData",action="store", dest="TheData", default='')

デフォルトの引数に、オプションに指定する値を指定しますが、オプションで引数を指定します。

于 2009-08-04T18:42:03.127 に答える
0

cpコマンドが理解することを確認した後、例えば--backup=simpleではなく --backup simple、次のように問題に答えました。

import sys
from optparse import OptionParser

def add_optval_option(pog, *args, **kwargs):
    if 'empty' in kwargs:
        empty_val = kwargs.pop('empty')
        for i in range(1, len(sys.argv)):
            a = sys.argv[i]
            if a in args:
                sys.argv.insert(i+1, empty_val)
                break
    pog.add_option(*args, **kwargs)

def main(args):
    parser = OptionParser()
    add_optval_option(parser,
                      '--foo', '-f',
                      default='MISSING',
                      empty='EMPTY',
                      help='"EMPTY" if given without a value. Note: '
                      '--foo=VALUE will work; --foo VALUE will *not*!')
    o, a = parser.parse_args(args)
    print 'Options:'
    print '  --foo/-f:', o.foo
    if a[1:]:
        print 'Positional arguments:'
        for arg in a[1:]:
            print ' ', arg
    else:
        print 'No positional arguments'

if __name__=='__main__':
    import sys
    main(sys.argv)

自己宣伝: これはopo私のパッケージのモジュールの一部thebopsです ... ;-)

于 2013-04-13T09:52:52.197 に答える
0

Mark Roddy のソリューションは機能しますが、実行時にパーサー オブジェクトの属性を変更する必要があり、- または -- 以外の代替オプション形式はサポートされていません。少し複雑な解決策は、optparse を実行する前に sys.argv 配列を変更し、引数を必要としないスイッチの後に空の文字列 ("") を挿入することです。この方法の唯一の制約は、sys.argv に挿入する値以外の予測可能な値にオプションをデフォルト設定することです (以下の例では [なし] を選択しましたが、実際には問題ありません)。

次のコードは、パーサーの例とオプションのセットを作成し、許可されたスイッチの配列をパーサーから抽出し (インスタンス変数マジックを少し使用して)、sys.argv を反復処理し、許可されたスイッチが見つかるたびに、その後に引数を指定せずに指定されたかどうかをチェックします。スイッチの後に引数がない場合、空の文字列がコマンド ラインに挿入されます。sys.argv を変更した後、パーサーが呼び出され、値が "" であるオプションをチェックし、それに応じて動作することができます。

#Instantiate the parser, and add some options; set the options' default values to None, or something predictable that
#can be checked later.
PARSER_DEFAULTVAL = None
parser = OptionParser(usage="%prog -[MODE] INPUT [options]")
#This method doesn't work if interspersed switches and arguments are allowed.
parser.allow_interspersed_args = False
parser.add_option("-d", "--delete", action="store", type="string", dest="to_delete", default=PARSER_DEFAULTVAL)
parser.add_option("-a", "--add", action="store", type="string", dest="to_add", default=PARSER_DEFAULTVAL)

#Build a list of allowed switches, in this case ['-d', '--delete', '-a', '--add'] so that you can check if something
#found on sys.argv is indeed a valid switch. This is trivial to make by hand in a short example, but if a program has
#a lot of options, or if you want an idiot-proof way of getting all added options without modifying a list yourself,
#this way is durable. If you are using OptionGroups, simply run the loop below with each group's option_list field.
allowed_switches = []
for opt in parser.option_list:
    #Add the short (-a) and long (--add) form of each switch to the list.
    allowed_switches.extend(opt._short_opts + opt._long_opts)

#Insert empty-string values into sys.argv whenever a switch without arguments is found.
for a in range(len(sys.argv)):
    arg = sys.argv[a]
    #Check if the sys.argv value is a switch
    if arg in allowed_switches:
        #Check if it doesn't have an accompanying argument (i.e. if it is followed by another switch, or if it is last
        #on the command line)
        if a == len(sys.argv) - 1 or argv[a + 1] in allowed_switches:
            sys.argv.insert(a + 1, "")

options, args = parser.parse_args()

#If the option is present (i.e. wasn't set to the default value)
if not (options.to_delete == PARSER_DEFAULTVAL):
    if options.droptables_ids_csv == "":
        #The switch was not used with any arguments.
        ...
    else:
        #The switch had arguments.
        ...
于 2011-11-10T15:01:48.340 に答える
0

Optparse ではすでに、空の文字列をオプション引数として渡すことができます。したがって、可能であれば、空の文字列を「値なし」として扱います。長いオプションの場合、次のいずれかが機能します。

my_script --opt=   --anotheroption
my_script --opt='' --anotheroption
my_script --opt="" --anotheroption
my_script --opt '' --anotheroption
my_script --opt "" --anotheroption

短いスタイルのオプションの場合、次のいずれかを使用できます。

my_script -o '' --anotheroption
my_script -o "" --anotheroption

警告: これは Linux でテストされており、他の Unix ライクなシステムでも同じように動作するはずです。Windows はコマンド ラインの引用符を別の方法で処理し、上記のバリアントのすべてを受け入れない場合があります。

于 2010-06-29T10:17:27.403 に答える