【问题标题】:Why does this argparse code behave differently between Python 2 and 3?为什么这个 argparse 代码在 Python 2 和 3 之间表现不同?
【发布时间】:2014-05-24 07:59:51
【问题描述】:

以下代码使用 argparse 的子解析器,在 Python 3 上失败,但在 Python 2 中按预期运行。比较文档后,我仍然不知道为什么。

#!/usr/bin/env python
from __future__ import print_function
from argparse import ArgumentParser


def action(args):
    print(args)

if __name__ == '__main__':
    std = ArgumentParser(add_help=False)
    std.add_argument('standard')

    ap = ArgumentParser()
    sp = ap.add_subparsers()

    cmd = sp.add_parser('subcommand', parents=[std], description='Do subcommand')
    cmd.add_argument('arg')
    cmd.set_defaults(do=action)

    args = ap.parse_args()
    args.do(args)

Python 2.7.6 的输出是:

me@computer$ python test.py 
usage: test.py [-h] {subcommand} ...
test.py: error: too few arguments

在 Python 3.3.5 中,我得到:

me@computer$ python3 test.py 
Traceback (most recent call last):
  File "test.py", line 21, in <module>
    args.do(args)
AttributeError: 'Namespace' object has no attribute 'do'

【问题讨论】:

  • 请注意,如果您使用子解析器:args = cmd.parse_args() 它会起作用。
  • 这段代码在 Python 2.7.4 上似乎给了我同样的错误。很可能您正在运行错误的文件版本或其他内容。它不应该工作。再仔细尝试一下。
  • 当我在 Python 2.7.6 解释器中输入您的代码时,我在 args = ap.parse_args() 行收到同样的错误。

标签: python python-3.x argparse python-2.x


【解决方案1】:

最新的argparse 版本改变了它测试所需参数的方式,子解析器从裂缝中消失了。它们不再是“必需的”。 http://bugs.python.org/issue9253#msg186387

当你得到test.py: error: too few arguments 时,它反对你没有给它一个“子命令”参数。在 3.3.5 中,它通过了该步骤,并返回 args

进行此更改后,3.3.5 的行为应该与早期版本相同:

ap = ArgumentParser()
sp = ap.add_subparsers(dest='parser')  # dest needed for error message
sp.required = True   # force 'required' testing

注意 - destrequired 都需要设置。需要dest 才能在错误消息中为该参数命名。


这个错误:

AttributeError: 'Namespace' object has no attribute 'do'

的产生是因为cmd 子解析器没有运行,并且没有将其参数(无论是否默认)放入命名空间。您可以通过定义另一个子解析器并查看生成的 args 来查看该效果。

【讨论】:

  • 谢谢,成功了。万一有什么奇怪的,这个解决方案向后兼容 Python 2.7
  • python 3.8.2.我试图设置所需的属性,但得到的是回溯而不是友好的帮助消息。文件“/usr/lib/python3.8/argparse.py”,第 2035 行,在 _parse_known_args ','.join(required_actions)) TypeError: sequence item 0: expected str instance, NoneType found
  • @tobixen,另见stackoverflow.com/q/23349349/901925。你设置dest了吗?
  • 不,没有尝试 dest(嗯,上面的答案中清楚地写了 dest 是必需的,奇怪的是我没有看到它)。我尝试设置 required=True 没有成功。最终做了一个解决方法 - github.com/tobixen/calendar-cli/commit/… - 也许我以错误的方式这样做,但是......它有效。
猜你喜欢
  • 1970-01-01
  • 2013-02-23
  • 1970-01-01
  • 1970-01-01
  • 2021-04-11
  • 1970-01-01
  • 2020-07-23
  • 2021-12-03
  • 1970-01-01
相关资源
最近更新 更多