Python 使用 getopt/optparse 为一个选项处理多个值?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4109436/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Processing multiple values for one single option using getopt/optparse?
提问by Open Grieves
Is it possible to fetch multiple values for one option using getopt or optparse, as shown in the example below:
是否可以使用 getopt 或 optparse 为一个选项获取多个值,如下例所示:
./hello_world -c arg1 arg2 arg3 -b arg4 arg5 arg6 arg7
Please note that the number of actual values for each option (-c, -b) could be either 1 or 100. I do not want to use:
./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"
It seems to me that this may not be possible (and perhaps in violation of POSIX), please correct me if I'm wrong.
在我看来这可能是不可能的(并且可能违反了 POSIX),如果我错了,请纠正我。
I've seen examples where all the non-options at the end of the line (./hello_world -c arg1 -b arg1 arg2 arg3) can be gathered... but not for the first of multiple option.
我见过一些示例,其中./hello_world -c arg1 -b arg1 arg2 arg3可以收集行 ( )末尾的所有非选项……但不是多个选项中的第一个。
I'd like my app to work on a wide range of platforms with different Python versions, so I've not looked at argparser.
我希望我的应用程序能够在具有不同 Python 版本的各种平台上运行,所以我没有看过 argparser。
回答by unutbu
You can do this with the nargsparameter in argparsewhich comes with Python2.7, and downloadable here.
您可以使用 Python2.7 附带的nargs参数来执行此操作argparse,可在此处下载。
I think it is one of the improvements added to argparsewhich is not in optparse. So, unfortunately, I don't think there is a nice way to handle this with optparseor getopt(which is even older).
我认为这是添加的改进之一,argparse而不是optparse. 所以,不幸的是,我不认为有一个很好的方法来处理这个optparse或getopt(甚至更老)。
A quick and dirty solution might be to forgo optparse/getop/argparseand just parse sys.argvyourself.
一个快速而肮脏的解决方案可能是放弃optparse/getop/argparse并sys.argv自己解析。
Or, going in the opposite direction, you might consider packaging a frozen copy of argparse (~88K) (renamed something like argparse_static) with your program, and
importing it like this:
或者,朝相反的方向发展,您可能会考虑将 argparse (~88K) 的冻结副本(重命名为argparse_static)与您的程序一起打包,然后像这样导入它:
try:
import argparse
except ImportError:
import argparse_static as argparse
That way, the program will use argparseif it is installed, and will use argparse_staticif it is not. Best of all, you won't have to rewrite much code as argparsebecomes standard.
这样,该程序argparse在安装时将使用,argparse_static如果未安装则将使用 。最重要的是,您不必像argparse标准那样重写太多代码。
回答by Martin v. L?wis
Neither getopt nor optparse support this out of the box. In addition, in the default (GNU) mode, the additional arguments would be treated as interspersed args, i.e. become available as left-over arguments at the end of the processing.
getopt 和 optparse 都不支持开箱即用。此外,在默认 (GNU) 模式下,附加参数将被视为散布的参数,即在处理结束时作为剩余参数可用。
The convention would be to require repeated mentioning of the same argument, i.e.
惯例是要求重复提及相同的论点,即
./hello_world -c arg1 -c arg2 -c arg3 -b arg4 -b arg5 -b arg6 -b arg7
This is will supported.
这将得到支持。
If you absolutely want to get it work the way you specify (i.e. both -b and -c extend until the next - argument or the end of the argument list), then you can hack something together based on optparse. Inherit from OptionParser, and override _process_short_opts. If it's one of your options, process it in the subclass, else forward to the base class.
如果您绝对想让它按照您指定的方式工作(即 -b 和 -c 都扩展到下一个 - 参数或参数列表的末尾),那么您可以基于 optparse 将某些东西组合在一起。从 OptionParser 继承,并覆盖 _process_short_opts。如果它是您的选择之一,请在子类中处理它,否则转发到基类。
回答by Richard Gomes
Yes, it can be done with optparse.
是的,它可以用 optparse 来完成。
This is an example:
这是一个例子:
./test.py --categories=aaa --categories=bbb --categories ccc arg1 arg2 arg3
which prints:
打印:
arguments: ['arg1', 'arg2', 'arg3']
options: {'categories': ['aaa', 'bbb', 'ccc']}
Full working example below:
下面的完整工作示例:
#!/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()
More information at http://docs.python.org/library/optparse.html#adding-new-actions
更多信息请访问http://docs.python.org/library/optparse.html#adding-new-actions
回答by estani
Another option would be to define a separator and process it locally, like the options in the mount command.
另一种选择是定义一个分隔符并在本地处理它,就像 mount 命令中的选项一样。
For example, if ,can be used as a separator:
例如,如果,可以用作分隔符:
...
args, _ = getopt.getopt(sys.argv[1:],'b:')
for flag, arg in args:
if flag=='-b': all_arguments = arg.split(',')
...
$ ./test -b opt1,opt2,opt3
Same for space! But then your users have to quote it properly.
空间也一样!但是你的用户必须正确引用它。
$ ./test -b 'opt1 opt2 opt3'
回答by Juan Carlos Moreno
Sorry to come late to the party but I just solved this with optparse using the nargs flag.
很抱歉来晚了,但我刚刚使用 nargs 标志通过 optparse 解决了这个问题。
parser.add_option('-c','--categories', dest='Categories', nargs=4 )
http://docs.python.org/2/library/optparse.html#optparse.Option.nargs
http://docs.python.org/2/library/optparse.html#optparse.Option.nargs
It is also worth noting, that argparse (suggested by unutbu) is now part of the standard python distribution while optparse is deprecated.
还值得注意的是,argparse(由 unutbu 建议)现在是标准 python 发行版的一部分,而 optparse 已弃用。
回答by Juan Carlos Moreno
Despite the claims of the other comments, this is possible with vanilla optparse, at least as of python 2.7. You just need to use action="append". From the docs:
尽管有其他评论的说法,但这对于 vanilla optparse 是可能的,至少从 python 2.7 开始。你只需要使用 action="append"。从文档:
parser.add_option("-t", "--tracks", action="append", type="int")
If -t3 is seen on the command-line, optparse does the equivalent of:
如果在命令行上看到 -t3,optparse 会执行以下操作:
options.tracks = []
options.tracks.append(int("3"))
If, a little later on, --tracks=4 is seen, it does:
如果稍后看到 --tracks=4 ,它会:
options.tracks.append(int("4"))
回答by Diego Navarro
An easier one:
一个更简单的:
make_option(
"-c",
"--city",
dest="cities",
action="append",
default=[],
help="specify cities",
)
Append actionis the easiest solution for this problem.
附加操作是解决此问题的最简单方法。

