当前位置: 首页 > 知识库问答 >
问题:

为什么 argparse 不接受 “--” 作为参数?

杨凌
2023-03-14

我的脚本将-d--delimiter作为参数:

parser.add_argument('-d', '--delimiter')

但当我将它作为分隔符传递时,它是空的

script.py --delimiter='--' 

我知道--在参数/参数解析中很特殊,但我以--选项='--'和引用的形式使用它。

为什么它不起作用?我使用的是Python 3.7.3

这是测试代码:

#!/bin/python3

import argparse

parser = argparse.ArgumentParser()
parser.add_argument('--delimiter')
parser.add_argument('pattern')

args = parser.parse_args()

print(args.delimiter)

当我运行它作为脚本--delimiter=--AAA它打印空args.delimiter

共有3个答案

南门嘉
2023-03-14

这个解决了这个特殊的问题。已经提出了补丁,但是还没有应用。Argparse错误地将“-”作为选项的参数

In [1]: import argparse
In [2]: p = argparse.ArgumentParser()
In [3]: a = p.add_argument('--foo')
In [4]: p.parse_args(['--foo=123'])
Out[4]: Namespace(foo='123')

意外情况:

In [5]: p.parse_args(['--foo=--'])
Out[5]: Namespace(foo=[])

完整的报价传递——但我不会深入讨论如何通过shell调用来实现这一点:

In [6]: p.parse_args(['--foo="--"'])
Out[6]: Namespace(foo='"--"')

“--”作为单独的字符串:

In [7]: p.parse_args(['--foo','--'])
usage: ipython3 [-h] [--foo FOO]
ipython3: error: argument --foo: expected one argument
...

双引号的另一个示例:

In [8]: p.parse_args(['--foo','"--"'])
Out[8]: Namespace(foo='"--"')

_parse_known_args中,输入被扫描并分类为“O”或“A”。'--'被处理为

        # all args after -- are non-options
        if arg_string == '--':
            arg_string_pattern_parts.append('-')
            for arg_string in arg_strings_iter:
                arg_string_pattern_parts.append('A')

我认为“--”在那之后被剥离了,但我还没有找到代码的那一部分。我也没有发现是“--foo=...”。版本已处理。

我依稀记得一些错误/问题处理多次发生的 '--'. 随着迁移到github,我不再像以前那样关注artparse开发。

get_values以以下内容开头:

def _get_values(self, action, arg_strings):
    # for everything but PARSER, REMAINDER args, strip out first '--'
    if action.nargs not in [PARSER, REMAINDER]:
        try:
            arg_strings.remove('--')
        except ValueError:
            pass

这就是为什么会导致空列表需要更多的思考和测试。

' = '在第一次扫描时使用的< code>_parse_optional中处理:

    # if the option string before the "=" is present, return the action
    if '=' in arg_string:
        option_string, explicit_arg = arg_string.split('=', 1)
        if option_string in self._option_string_actions:
            action = self._option_string_actions[option_string]
            return action, option_string, explicit_arg

argparse不正确地处理args中的多个“-”

Argparse:允许使用--打破nargs并进入子解析

这个解决了这个特殊的问题。已经提出了补丁,但是还没有应用。Argparse错误地将“-”作为选项的参数

卓星波
2023-03-14

它调用parse_args调用parse_known_args调用_parse_known_args

然后,在第 2078 行(或类似的东西)上,它执行以下操作(在通过字符串的 while 循环中):

start_index = consume_optional(start_index)

调用< code>_parse_known_args方法中定义的< code>consume_optional(这是有意义的,因为这是它现在正在解析的可选参数)。当给定< code> - delimiter=' - '时,它将使这个< code>action_tuples:

# if the action expect exactly one argument, we've
# successfully matched the option; exit the loop
elif arg_count == 1:
    stop = start_index + 1
    args = [explicit_arg]
    action_tuples.append((action, args, option_string))
    break

##
## The above code gives you the following:
##
action_tuples=[(_StoreAction(option_strings=['-d', '--delimiter'], dest='delimiter', nargs=None, const=None, default=None, type=None, choices=None, help=None, metavar=None), ['--'], '--delimiter')]

然后迭代到,然后在第2009行上馈送到<code>take_action</code>:

assert action_tuples
for action, args, option_string in action_tuples:
    take_action(action, args, option_string)
    return stop

然后,take_action函数将调用self_第1918行的get_values(action,argument_strings),正如@hpaulj在回答中所提到的,它删除了--。然后,剩下的是空名单。

易研
2023-03-14

这看起来像一个错误。你应该举报。

< code>argparse.py中的这段代码是< code>_get_values的开始,它是解析值的主要帮助函数之一:

if action.nargs not in [PARSER, REMAINDER]:
    try:
        arg_strings.remove('--')
    except ValueError:
        pass

代码接收--参数作为列表['--']的单个元素。它尝试从列表中删除'--',因为当使用--作为选项结束标记时,'--'字符串最终将在arg_strings中用于_get_values调用之一。但是,当'--'是实际参数值时,代码仍然会删除它,因此arg_strings最终会成为一个空列表而不是单个元素列表。

然后,代码通过一个eles-if链来处理不同类型的参数(此处省略了分支机构以节省空间):

# optional argument produces a default when not present
if not arg_strings and action.nargs == OPTIONAL:
    ...
# when nargs='*' on a positional, if there were no command-line
# args, use the default if it is anything other than None
elif (not arg_strings and action.nargs == ZERO_OR_MORE and
      not action.option_strings):
    ...
# single argument or optional argument produces a single value
elif len(arg_strings) == 1 and action.nargs in [None, OPTIONAL]:
    ...
# REMAINDER arguments convert all values, checking none
elif action.nargs == REMAINDER:
    ...
# PARSER arguments convert all values, but check only the first
elif action.nargs == PARSER:
    ...
# SUPPRESS argument does not put anything in the namespace
elif action.nargs == SUPPRESS:
    ...
# all other types of nargs produce a list
else:
    ...

该代码应通过第三分支,

# single argument or optional argument produces a single value
elif len(arg_strings) == 1 and action.nargs in [None, OPTIONAL]:

但是,由于<code>arg_strings</code>中缺少参数,<code>len(arg_ strings)</code>为0。相反,它命中了最后一个案例,该案例应该处理完全不同类型的参数。该分支最终返回一个空列表,而不是本应返回的<code>字符串--</code>字符串,这就是<code>参数的原因。分隔符最终是一个空列表,而不是字符串。

这个错误也体现在位置参数上。举个例子,

import argparse

parser = argparse.ArgumentParser()
parser.add_argument('a')
parser.add_argument('b')

args = parser.parse_args(["--", "--", "--"])

print(args)

指纹

Namespace(a='--', b=[])

因为当< code>_get_values处理< code>b参数时,它将< code>[' - ']作为< code>arg_strings接收,并删除< code>' - '。当处理< code>a参数时,它接收< code>[' -','- '],表示一个选项结束标记和一个实际的< code> - 参数值,并且它成功地移除了选项结束标记,但是当处理< code>b时,它移除了实际的参数值。

 类似资料:
  • 问题内容: 我遇到了-在我看来-奇怪的行为: 为什么str.split()不会接受关键字参数,即使这很有意义?我在Python2和Python3中都发现了这种现象。 问题答案: 见这个bug和它的superseder。 是CPython中的本机函数,因此具有此处描述的行为: CPython实现细节: 一个实现可能会提供内置函数,这些函数的位置参数没有名称,即使出于文档目的而对其进行了“命名”,因此

  • 红线位于“打开导航抽屉”和“关闭导航抽屉”下 这张图片显示了这个问题

  • 我正在使用python和argparse编写脚本: 我希望能够运行它与python3parseab.py-a 11-b 22-a 33,和函数A将执行两次与11和33,和函数B一次与22。 现在每个功能只发生一次。 *我不想在每个选项后接受更多参数,而是希望能够接受同一函数的多个实例。 谢谢你!

  • 问题内容: 我正在尝试使用argparse接受type = dict的参数,但是无论输入如何,都会给出无效dict值的错误。 这是我尝试将字典传递给脚本时发生的情况 查看这些文件,我认为这是可能的。 http://docs.python.org/dev/library/argparse.html “任何支持in运算符的对象都可以作为options值传递,因此dict对象,set对象,自定义容器等都

  • 问题内容: 阅读@RequestMapping文档:http : //static.springsource.org/spring/docs/2.5.x/api/org/springframework/web/bind/annotation/RequestMapping.html 它接受String数组参数作为其路径映射。 所以这可以使用java: 但是在scala中,我需要使用: Scala版本