【问题标题】:Configure argparse to accept quoted arguments配置 argparse 以接受带引号的参数
【发布时间】:2017-12-22 03:18:41
【问题描述】:

我正在编写一个程序,除其他外,它允许用户通过参数指定要加载的模块(然后用于执行操作)。我正在尝试设置一种方法来轻松地将参数传递给这个内部模块,并且我试图使用 ArgParse 的 action='append' 让它构建一个我将传递的参数列表。

这是我正在使用的参数的基本布局

parser.add_argument('-M', '--module',
                    help="Module to run on changed files - should be in format MODULE:CLASS\n\
                          Specified class must have function with the signature run(src, dest)\
                          and return 0 upon success",
                    required=True)
parser.add_argument('-A', '--module_args',
                    help="Arg to be passed through to the specified module",
                    action='append',
                    default=[])

但是 - 如果我然后尝试使用 python my_program -M module:class -A "-f filename" 运行这个程序(我想通过 -f filename 到我的模块)它似乎正在解析 -f 作为它自己的参数(我得到错误my_program: error: argument -A/--module_args: expected one argument

有什么想法吗?

【问题讨论】:

  • 查看sys.argv。引号是通过解析器还是被外壳吞噬?

标签: python argparse


【解决方案1】:

与:

import argparse

parser = argparse.ArgumentParser()
parser.add_argument('-M', '--module',
                    help="Module to run on changed files - should be in format MODULE:CLASS\n\
                          Specified class must have function with the signature run(src, dest)\
                          and return 0 upon success",
                    )
parser.add_argument('-A', '--module_args',
                    help="Arg to be passed through to the specified module",
                    action='append',
                    default=[])
import sys
print(sys.argv)
print(parser.parse_args())

我明白了:

1028:~/mypy$ python stack45146728.py -M module:class -A "-f filename"
['stack45146728.py', '-M', 'module:class', '-A', '-f filename']
Namespace(module='module:class', module_args=['-f filename'])

这是使用 linux shell。引用的字符串仍然是一个字符串,如 sys.argv 中所示,并被正确解释为 -A 的参数。

如果没有引号,-f 是单独的并被解释为一个标志。

1028:~/mypy$ python stack45146728.py -M module:class -A -f filename
['stack45146728.py', '-M', 'module:class', '-A', '-f', 'filename']
usage: stack45146728.py [-h] [-M MODULE] [-A MODULE_ARGS]
stack45146728.py: error: argument -A/--module_args: expected one argument

您是否使用windows 或其他不以相同方式处理引号的操作系统/shell?


在Argparse `append` not working as expected

您询问了一个稍微不同的命令行:

1032:~/mypy$ python stack45146728.py  -A "-k filepath" -A "-t"
['stack45146728.py', '-A', '-k filepath', '-A', '-t']
usage: stack45146728.py [-h] [-M MODULE] [-A MODULE_ARGS]
stack45146728.py: error: argument -A/--module_args: expected one argument

正如我已经注意到的,-k filepath 作为一个字符串传递。由于空间的原因,argparse 不会将其解释为标志。但它确实将裸露的 '-t' 解释为一个标志。

关于将未定义的“-xxx”字符串解释为参数而不是标志的可能性存在错误/问题。我必须查一下,看看是否有任何东西可以投入生产。

字符串如何分类为标志或参数的详细信息可以在argparse.ArgumentParser._parse_optional 方法中找到。它包含一条评论:

    # if it contains a space, it was meant to be a positional
    if ' ' in arg_string:
        return None

http://bugs.python.org/issue9334 argparse does not accept options taking arguments beginning with dash (regression from optparse) 是该主题的一个古老而长期的错误/问题。

【讨论】:

  • 感谢(交叉问题)回答!似乎只是用空格填充这些引用的 args 并尝试指导我的用户有关此解决方法现在必须做
【解决方案2】:

解决方案是接受任意参数 - argparse 的文档here 中有一个示例:

argparse.REMAINDER。所有剩余的命令行参数都被收集到一个列表中。这对于调度到其他命令行实用程序的命令行实用程序通常很有用:

>>> parser = argparse.ArgumentParser(prog='PROG')
>>> parser.add_argument('--foo')
>>> parser.add_argument('command')
>>> parser.add_argument('args', nargs=argparse.REMAINDER)
>>> print(parser.parse_args('--foo B cmd --arg1 XX ZZ'.split()))
Namespace(args=['--arg1', 'XX', 'ZZ'], command='cmd', foo='B')

【讨论】:

  • 这是一个有趣的解决方案——但我相信(至少对于我的应用程序)不接受任意命令参数会更好。至少使用空格填充的解决方法,用户仍然必须有意使用-A 参数
猜你喜欢
  • 2012-10-21
  • 1970-01-01
  • 1970-01-01
  • 2018-04-22
  • 2021-07-15
  • 2020-11-25
  • 2017-12-14
  • 2012-10-13
  • 2013-01-24
相关资源
最近更新 更多