Python 无法让 argparse 读取带破折号的带引号的字符串?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/16174992/
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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-18 21:56:52  来源:igfitidea点击:

Can't get argparse to read quoted string with dashes in it?

pythonargparsecommand-line-interface

提问by sfendell

Is there a way to make argparse recognize anything between two quotes as a single argument? It seems to keep seeing the dashes and assuming that it's the start of a new option

有没有办法让 argparse 将两个引号之间的任何内容识别为单个参数?它似乎一直在看到破折号并假设这是一个新选项的开始

I have something like:

我有类似的东西:

mainparser = argparse.ArgumentParser()
subparsers = mainparser.add_subparsers(dest='subcommand')
parser = subparsers.add_parser('queue')
parser.add_argument('-env', '--extraEnvVars', type=str,
                        help='String of extra arguments to be passed to model.')
...other arguments added to parser...

But when I run:

但是当我运行时:

python Application.py queue -env "-s WHATEVER -e COOL STUFF"

It gives me:

它给了我:

Application.py queue: error: argument -env/--extraEnvVars: expected one argument

If I leave off the first dash, it works totally fine, but it's kind of crucial that I be able to pass in a string with dashes in it. I've tried escaping it with \ , which causes it to succeed but adds the \ to the argument string Does anyone know how to get around this? This happens whether or not -s is an argument in parser.

如果我去掉第一个破折号,它完全可以正常工作,但是我能够传入一个带破折号的字符串是至关重要的。我试过用 \ 转义它,这会导致它成功,但将 \ 添加到参数字符串中 有谁知道如何解决这个问题?无论 -s 是否是解析器中的参数,都会发生这种情况。

EDIT: I'm using Python 2.7.

编辑:我使用的是 Python 2.7。

EDIT2:

编辑2:

python Application.py -env " -env"

works perfectly fine, but

工作得很好,但是

python Application.py -env "-env"

does not.

才不是。

EDIT3: Looks like this is actually a bug that's being debated already: http://www.gossamer-threads.com/lists/python/bugs/89529, http://python.6.x6.nabble.com/issue9334-argparse-does-not-accept-options-taking-arguments-beginning-with-dash-regression-from-optp-td578790.html. It's only in 2.7 and not in optparse.

EDIT3:像这个看起来是实际就是BEING已经讨论了一个错误:http://www.gossamer-threads.com/lists/python/bugs/89529http://python.6.x6.nabble.com/issue9334- argparse-does-not-accept-options-taking-arguments-beginning-with-dash-regression-from-optp-td578790.html。它仅在 2.7 中而不在 optparse 中。

EDIT4: The current open bug report is: http://bugs.python.org/issue9334

EDIT4:当前打开的错误报告是:http://bugs.python.org/issue9334

采纳答案by William

You can start the argument with a space python tst.py -e ' -e blah'as a very simple workaround. Simply lstrip()the option to put it back to normal, if you like.

python tst.py -e ' -e blah'作为一个非常简单的解决方法,您可以用空格开始争论。lstrip()如果您愿意,只需将其恢复正常的选项。

Or, if the first "sub-argument" is not also a valid argument to the original function then you shouldn't need to do anything at all. That is, the only reason that python tst.py -e '-s hi -e blah'doesn't work is because -sis a valid option to tst.py.

或者,如果第一个“子参数”也不是原始函数的有效参数,那么您根本不需要做任何事情。也就是说,python tst.py -e '-s hi -e blah'不起作用的唯一原因是因为-stst.py.

Also, the optparsemodule, now deprecated, works without any issue.

此外,现在已弃用的optparse模块可以正常工作。

回答by SethMMorton

Updated answer:

更新的答案:

You can put an equals sign when you call it:

你可以在调用时加上等号:

python Application.py -env="-env"


Original answer:

原答案:

I too have had troubles doing what you are trying to do, but there is a workaround build into argparse, which is the parse_known_argsmethod. This will let all arguments that you haven't defined pass through the parser with the assumption that you would use them for a subprocess. The drawbacks are that you won't get error reporting with bad arguments, and you will have to make sure that there is no collision between your options and your subprocess's options.

我在执行您尝试执行的操作时也遇到了麻烦,但是 argparse 中内置了一个变通方法,即parse_known_args方法。这将使您尚未定义的所有参数通过解析器,并假设您将它们用于子流程。缺点是您不会收到带有错误参数的错误报告,并且您必须确保您的选项和子流程的选项之间没有冲突。

Another option could be to force the user's to use a plus instead of a minus:

另一种选择是强制用户使用加号而不是减号:

python Application.py -e "+s WHATEVER +e COOL STUFF"

and then you change the '+' to '-' in post processing before passing to your subprocess.

然后在传递给子流程之前,在后期处理中将“+”更改为“-”。

回答by hpaulj

This issue is discussed in depth in http://bugs.python.org/issue9334. Most of the activity was in 2011. I added a patch last year, but there's quite a backlog of argparsepatches.

这个问题在http://bugs.python.org/issue9334中有深入讨论。大部分活动发生在 2011 年。我去年添加了一个补丁,但argparse补丁积压了很多。

At issue is the potential ambiguity in a string like '--env', or "-s WHATEVER -e COOL STUFF"when it follows an option that takes an argument.

问题在于像 那样的字符串中潜在的歧义'--env',或者"-s WHATEVER -e COOL STUFF"当它跟在一个带参数的选项之后。

optparsedoes a simple left to right parse. The first --envis an option flag that takes one argument, so it consumes the next, regardless of what it looks like. argparse, on the other hand, loops through the strings twice. First it categorizes them as 'O' or 'A' (option flag or argument). On the second loop it consumes them, using a relike pattern matching to handle variable nargsvalues. In this case it looks like we have OO, two flags and no arguments.

optparse做一个简单的从左到右的解析。第一个--env是一个选项标志,它接受一个参数,所以它使用下一个参数,不管它看起来像什么。 argparse,另一方面,循环遍历字符串两次。首先,它将它们归类为“O”或“A”(选项标志或参数)。在第二个循环中,它使用它们,使用re类似的模式匹配来处理变量nargs值。在这种情况下,看起来我们有OO两个标志并且没有参数。

The solution when using argparseis to make sure an argument string will not be confused for an option flag. Possibilities that have been shown here (and in the bug issue) include:

使用时的解决方案argparse是确保参数字符串不会与选项标志混淆。此处(以及错误问题)显示的可能性包括:

--env="--env"  # clearly defines the argument.

--env " --env"  # other non - character
--env "--env "  # space after

--env "--env one two"  # but not '--env "-env one two"'

By itself '--env'looks like a flag (even when quoted, see sys.argv), but when followed by other strings it does not. But "-env one two"has problems because it can be parsed as ['-e','nv one two'], a `'-e' flag followed by a string (or even more options).

本身'--env'看起来像一个标志(即使被引用,请参阅sys.argv),但当后面跟其他字符串时,它不是。但是"-env one two"有问题,因为它可以被解析为['-e','nv one two'],一个 `'-e' 标志后跟一个字符串(甚至更多的选项)。

--and nargs=argparse.PARSERcan also be used to force argparseto view all following strings as arguments. But they only work at the end of argument lists.

--并且nargs=argparse.PARSER还可以用来强制argparse查看所有下列字符串作为参数。但它们只在参数列表的末尾工作。

There is a proposed patch in issue9334 to add a args_default_to_positional=Truemode. In this mode, the parser only classifies strings as option flags if it can clearly match them with defined arguments. Thus '--one' in '--env --one' would be classed as as an argument. But the second '--env' in '--env --env' would still be classed as an option flag.

在 issue9334 中有一个建议的补丁来添加一个args_default_to_positional=True模式。在这种模式下,解析器仅将字符串分类为选项标志,前提是它可以与定义的参数明确匹配。因此,'--env --one' 中的 '--one' 将被归类为参数。但是 '--env --env' 中的第二个 '--env' 仍将被归类为选项标志。



Expanding on the related case in

展开相关案例

Using argparse with argument values that begin with a dash ("-")

将 argparse 与以破折号(“-”)开头的参数值一起使用

parser = argparse.ArgumentParser(prog="PROG")
parser.add_argument("-f", "--force", default=False, action="store_true")
parser.add_argument("-e", "--extra")
args = parser.parse_args()
print(args)

produces

产生

1513:~/mypy$ python3 stack16174992.py --extra "--foo one"
Namespace(extra='--foo one', force=False)
1513:~/mypy$ python3 stack16174992.py --extra "-foo one"
usage: PROG [-h] [-f] [-e EXTRA]
PROG: error: argument -e/--extra: expected one argument
1513:~/mypy$ python3 stack16174992.py --extra "-bar one"
Namespace(extra='-bar one', force=False)
1514:~/mypy$ python3 stack16174992.py -fe one
Namespace(extra='one', force=True)

The "-foo one" case fails because the -foois interpreted as the -fflag plus unspecified extras. This is the same action that allows -feto be interpreted as ['-f','-e'].

“-foo one”情况失败,因为-foo被解释为-f标志加上未指定的附加项。这是允许-fe解释为相同的操作['-f','-e']

If I change the nargsto REMAINDER(not PARSER), everything after -eis interpreted as arguments for that flag:

如果我将nargsto REMAINDER(not PARSER)更改为(not ),则后面的所有内容都将-e被解释为该标志的参数:

parser.add_argument("-e", "--extra", nargs=argparse.REMAINDER)

All cases work. Note the value is a list. And quotes are not needed:

所有案例都有效。请注意,该值是一个列表。并且不需要引号:

1518:~/mypy$ python3 stack16174992.py --extra "--foo one"
Namespace(extra=['--foo one'], force=False)
1519:~/mypy$ python3 stack16174992.py --extra "-foo one"
Namespace(extra=['-foo one'], force=False)
1519:~/mypy$ python3 stack16174992.py --extra "-bar one"
Namespace(extra=['-bar one'], force=False)
1519:~/mypy$ python3 stack16174992.py -fe one
Namespace(extra=['one'], force=True)
1520:~/mypy$ python3 stack16174992.py --extra --foo one
Namespace(extra=['--foo', 'one'], force=False)
1521:~/mypy$ python3 stack16174992.py --extra -foo one
Namespace(extra=['-foo', 'one'], force=False)

argparse.REMAINDERis like '*', except it takes everything that follows, whether it looks like a flag or not. argparse.PARSERis more like '+', in that it expects a positionallike argument first. It's the nargsthat subparsersuses.

argparse.REMAINDER就像'*',除了它后面的所有内容,无论它是否看起来像一个标志。 argparse.PARSER更像是“+”,因为它首先需要一个positional类似的参数。就是nargs那个subparsers用。

This uses of REMAINDERis documented, https://docs.python.org/3/library/argparse.html#nargs

这种用途REMAINDER被记录在案,https://docs.python.org/3/library/argparse.html#nargs

回答by Gowtham MS

paser.add_argument("--argument_name", default=None, nargs=argparse.REMAINDER)

python_file.py --argument_name "--abc=10 -a=1 -b=2 cdef"

python_file.py --argument_name "--abc=10 -a=1 -b=2 cdef"

Note: the argument values have to be passed only within double quotes and this doesn't work with single quotes

注意:参数值只能在双引号内传递,这不适用于单引号