2017-07-17 103 views
0

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

这里的参数的基本布局,我使用

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

任何想法

+1

看看'sys.argv'。引号是通过解析器还是被shell所吞噬? – hpaulj

回答

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或一些其他OS /外壳,不处理引号以同样的方式?


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通过为一个字符串传递。由于空间的原因,​​不会将其解释为标志。但它确实将这个光秃秃的'-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/issue9334argparse does not accept options taking arguments beginning with dash (regression from optparse)是对话题的老长的bug /问题。

+0

感谢(交叉问题)答案!它似乎只是用一个空格填充这些引用的参数,并试图指导我的用户有关此解决方法现在必须执行的操作 – wKavey

0

解决的办法是接受任意参数 - ?有在示例argparse's doc 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') 
+0

这是一个有趣的解决方案 - 但是我相信它会更好(至少对我的应用程序来说)不接受任意的命令参数。至少用填充空格的解决方法,用户仍然必须有意使用'-A'参数 – wKavey