29

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

./hello_world -c arg1 arg2 arg3 -b arg4 arg5 arg6 arg7

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

在我看来,这可能是不可能的(并且可能违反了 POSIX),如果我错了,请纠正我。

./hello_world -c arg1 -b arg1 arg2 arg3我已经看到可以收集行尾 ( ) 的所有非选项的示例......但不是多个选项中的第一个。

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

4

7 回答 7

18

是的,它可以用 optparse 完成。

这是一个例子:

./test.py --categories=aaa --categories=bbb --categories ccc arg1 arg2 arg3

打印:

arguments: ['arg1', 'arg2', 'arg3']
options: {'categories': ['aaa', 'bbb', 'ccc']}

下面的完整工作示例:

#!/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()

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

于 2012-05-01T21:44:52.337 回答
11

尽管有其他评论的说法,但至少从 python 2.7 开始,vanilla optparse 是可能的。您只需要使用 action="append"。从文档

parser.add_option("-t", "--tracks", action="append", type="int")

如果在命令行上看到 -t3,则 optparse 等效于:

options.tracks = []
options.tracks.append(int("3"))

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

options.tracks.append(int("4"))
于 2014-05-02T21:58:07.883 回答
8

很抱歉参加聚会迟到了,但我刚刚使用 nargs 标志通过 optparse 解决了这个问题。

parser.add_option('-c','--categories', dest='Categories', nargs=4 )

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

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

于 2013-02-12T01:29:51.713 回答
7

另一种选择是定义一个分隔符并在本地处理它,就像 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

空间也一样!但是你的用户必须正确引用它。

$ ./test -b 'opt1 opt2 opt3'
于 2012-08-06T15:10:44.573 回答
6

getopt 和 optparse 均不支持此功能。此外,在默认 (GNU) 模式下,附加参数将被视为散布参数,即在处理结束时作为剩余参数可用。

惯例是要求重复提及相同的论点,即

./hello_world -c arg1 -c arg2 -c arg3 -b arg4 -b arg5 -b arg6 -b arg7

这将得到支持。

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

于 2010-11-05T20:11:36.857 回答
5

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

我认为这是添加的改进之一,argparse不在optparse. 所以,不幸的是,我不认为有一个很好的方法可以用optparseor getopt(它甚至更老)来处理这个问题。

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

或者,朝相反的方向发展,您可能会考虑将 argparse (~88K) 的冻结副本(重命名为argparse_static)与您的程序一起打包,然后像这样导入它:

try:
    import argparse
except ImportError:
    import argparse_static as argparse

这样,程序argparse安装时使用,未安装时使用 argparse_static。最重要的是,您不必像argparse标准那样重写太多代码。

于 2010-11-05T20:10:45.700 回答
3

一个更简单的:

make_option(
    "-c",
    "--city",
    dest="cities",
    action="append",
    default=[],
    help="specify cities",
)

附加操作是解决此问题的最简单方法。

于 2014-07-28T08:32:45.233 回答