使用getopt/optparse为一个选项处理多个值?

Ope*_*ves 27 python getopt

是否可以使用getopt或optparse为一个选项获取多个值,如下例所示:

./hello_world -c arg1 arg2 arg3 -b arg4 arg5 arg6 arg7
Run Code Online (Sandbox Code Playgroud)

请注意,每个选项(-c,-b)的实际值数可以是1或100.我不想使用: ./hello_world -c "arg1 arg2 arg3" -b "arg4 arg5 arg6 arg7"

在我看来,这可能是不可能的(也许违反了POSIX),如果我错了,请纠正我.

我已经看到了一些例子,其中./hello_world -c arg1 -b arg1 arg2 arg3可以收集line()末尾的所有非选项......但不是第一个多选项.

我希望我的应用程序可以在不同的Python版本的各种平台上工作,所以我没有看过argparser.

Ric*_*mes 15

是的,可以使用optparse来完成.

这是一个例子:

./test.py --categories=aaa --categories=bbb --categories ccc arg1 arg2 arg3
Run Code Online (Sandbox Code Playgroud)

打印:

arguments: ['arg1', 'arg2', 'arg3']
options: {'categories': ['aaa', 'bbb', 'ccc']}
Run Code Online (Sandbox Code Playgroud)

完整的工作示例如下:

#!/usr/bin/env python

import os, sys
from optparse import OptionParser
from optparse import Option, OptionValueError

VERSION = '0.9.4'

class MultipleOption(Option):
    ACTIONS = Option.ACTIONS + ("extend",)
    STORE_ACTIONS = Option.STORE_ACTIONS + ("extend",)
    TYPED_ACTIONS = Option.TYPED_ACTIONS + ("extend",)
    ALWAYS_TYPED_ACTIONS = Option.ALWAYS_TYPED_ACTIONS + ("extend",)

    def take_action(self, action, dest, opt, value, values, parser):
        if action == "extend":
            values.ensure_value(dest, []).append(value)
        else:
            Option.take_action(self, action, dest, opt, value, values, parser)


def main():
    PROG = os.path.basename(os.path.splitext(__file__)[0])
    long_commands = ('categories')
    short_commands = {'cat':'categories'}
    description = """Just a test"""
    parser = OptionParser(option_class=MultipleOption,
                          usage='usage: %prog [OPTIONS] COMMAND [BLOG_FILE]',
                          version='%s %s' % (PROG, VERSION),
                          description=description)
    parser.add_option('-c', '--categories', 
                      action="extend", type="string",
                      dest='categories', 
                      metavar='CATEGORIES', 
                      help='comma separated list of post categories')

    if len(sys.argv) == 1:
        parser.parse_args(['--help'])

    OPTIONS, args = parser.parse_args()
    print "arguments:", args
    print "options:", OPTIONS

if __name__ == '__main__':
    main()
Run Code Online (Sandbox Code Playgroud)

有关更多信息,请访问http://docs.python.org/library/optparse.html#adding-new-actions


小智 11

尽管其他评论的主张,这可能与vanilla optparse,至少从python 2.7.你只需要使用action ="append".来自文档:

parser.add_option("-t", "--tracks", action="append", type="int")
Run Code Online (Sandbox Code Playgroud)

如果在命令行中看到-t3,则optparse相当于:

options.tracks = []
options.tracks.append(int("3"))
Run Code Online (Sandbox Code Playgroud)

如果稍后,看到--tracks = 4,它会:

options.tracks.append(int("4"))
Run Code Online (Sandbox Code Playgroud)


Jua*_*eno 8

很抱歉来参加聚会,但我刚用optparse使用nargs标志解决了这个问题.

parser.add_option('-c','--categories', dest='Categories', nargs=4 )
Run Code Online (Sandbox Code Playgroud)

http://docs.python.org/2/library/optparse.html#optparse.Option.nargs

值得注意的是,argparse(由unutbu建议)现在是标准python发行版的一部分,而optparse已被弃用.


unu*_*tbu 5

您可以使用Python2.7附带的nargs参数执行此操作argparse,也可以在此处下载.

我认为这是增加的改进argparse之一optparse.所以,不幸的是,我不认为有一个很好的方法来处理这个optparsegetopt(甚至更老).

一个快速而肮脏的解决方案可能是放弃optparse/getop/argparse并解析sys.argv自己.

或者,在相反的方向上,你可以考虑argparse_static用你的程序打包argparse(~88K)的冷冻副本(重命名之类),并像这样导入它:

try:
    import argparse
except ImportError:
    import argparse_static as argparse
Run Code Online (Sandbox Code Playgroud)

这样,程序将argparse在安装时使用,argparse_static如果不安装则使用 .最重要的是,您不必重写大量代码作为argparse标准.


Mar*_*wis 5

getopt和optparse都不支持开箱即用.此外,在默认(GNU)模式下,附加参数将被视为散布的args,即在处理结束时可用作剩余参数.

该公约将要求重复提及相同的论点,即

./hello_world -c arg1 -c arg2 -c arg3 -b arg4 -b arg5 -b arg6 -b arg7
Run Code Online (Sandbox Code Playgroud)

这将得到支持.

如果你绝对想让它按照你指定的方式工作(即-b和-c都延伸到下一个 - 参数或参数列表的结尾),那么你可以根据optparse一起破解.从OptionParser继承,并覆盖_process_short_opts.如果它是您的选项之一,请在子类中处理它,否则转发到基类.


est*_*ani 5

另一个选择是定义一个分隔符并在本地对其进行处理,就像mount命令中的选项一样。

例如,如果,可以用作分隔符:

...
args, _ = getopt.getopt(sys.argv[1:],'b:')
for flag, arg in args:
  if flag=='-b': all_arguments = arg.split(',')
...

$ ./test -b opt1,opt2,opt3
Run Code Online (Sandbox Code Playgroud)

空间一样!但是,然后您的用户必须正确引用它。

$ ./test -b 'opt1 opt2 opt3'
Run Code Online (Sandbox Code Playgroud)