带有可选参数的ArgumentParser(在mutual_exclusive_group中)

时间:2013-12-31 11:25:50

标签: python python-2.7 arguments argparse

我正在尝试做一件非常简单的事情 - 只有两个选项:-p-c,相互排斥,可能有也可能没有参数,带有可选参数的th...is或没有一个th...at。这就是我得到的:

def main():

    import argparse
    parser = argparse.ArgumentParser(description = '''ArgParser with optional argument''',
                                     argument_default = argparse.SUPPRESS)

    group1 = parser.add_mutually_exclusive_group(required=True)

    group1.add_argument('-p', '--project', dest='proj',
                        nargs='?', const='all', type=str,
                        help='list of project(s)')
    group1.add_argument('-c', '--component', dest='comp',
                        nargs='?', const='all', type=str,
                        help='list of Component(s)')

    args = parser.parse_args()
    print(args)

    if args.proj:
        outString = 'project/'+args.proj if args.proj is not 'all' else 'projects'
    elif args.comp:
        outString = 'component/'+args.comp if args.comp is not 'all' else 'components'
    else: pass

    print('OutPutString: '+outString)

if __name__ == "__main__":

    import sys
    try: sys.exit(main())
    except KeyboardInterrupt: pass
    finally: print

适用于if-elif-else块中的第一个条件,因此可以正常工作:

dass@mon105:~$ ./argParseOpts.py -p 
Namespace(proj='all')
OutPutString: projects
#
dass@mon105:~$ ./argParseOpts.py -p testing
Namespace(proj='testing')
OutPutString: project/testing

但不是-c代替-p(即第二个条件):

dass@mon105:~$ ./argParseOpts.py -c 
Namespace(comp='all')

Traceback (most recent call last):
  File "./argParseOpts.py", line 32, in <module>
    try: sys.exit(main())
  File "./argParseOpts.py", line 21, in main
    if args.proj:
AttributeError: 'Namespace' object has no attribute 'proj'

任何人都可以告诉我,如果我遗失任何东西或做任何根本错误的事情吗?使用v2.7.2,如果重要的话。干杯!!

3 个答案:

答案 0 :(得分:1)

由于您将argument_default值设置为argparse.SUPPRESS,因此未设置任何属性,这意味着除非属性具有显式值,否则永远不会设置属性。

Set可以为每个参数设置一个显式的default=None值,以便为这些特定选项再次获取属性:

group1.add_argument('-p', '--project', dest='proj',
                    nargs='?', const='all', type=str,
                    help='list of project(s)', default=None)
group1.add_argument('-c', '--component', dest='comp',
                    nargs='?', const='all', type=str,
                    help='list of Component(s)', default=None)

将再次设置args.projargs.comp属性。 None是一个假值,因此if args.proj测试不会传递到另一个分支,例如。

另一种方法是使用hasattr()查看属性是否已设置:

if hasattr(args, 'proj'):

答案 1 :(得分:0)

由于已经使用Argparse回答了该问题,我建议您使用docopt作为替代方案。以标准格式编写界面帮助消息,这就是您需要做的所有事情。如果我理解你的使用方法就是这样。

在这种情况下解决问题的关键是制作-p-c标记,并为字符串使用不同的变量NAME

"""Usage:
    myprog (-p [NAME] | -c [NAME])

Options:
    -p, --project        list of project(s)
    -c, --component      list of component(s)
"""
from docopt import docopt

if __name__ == "__main__":
    arguments = docopt(__doc__)
    print(arguments)

    name = 'all' if arguments['NAME'] is None else arguments['NAME']
    if arguments['--project']:
        ...
    elif arguments['--component']:
        ...

如果我们只打印参数,则使用模式将如下所示。

$ python myprog.py
Usage:
...

$ python myprog.py -p
{'--project': True,
 '--component': False,
 'NAME': None}

$ python myprog.py -c foo
{'--project': False,
 '--component': True,
 'NAME': 'foo'}

$ python myprog.py -p foo -c bar
Usage:
...

答案 2 :(得分:0)

错误原因是SUPPRESS

parser = argparse.ArgumentParser(description = '''ArgParser with optional argument''',
                                 argument_default = argparse.SUPPRESS)

使用此选项,如果参数未显示在argv中,则它不会显示在Namespace中。

dass@mon105:~$ ./argParseOpts.py -c 
Namespace(comp='all')

Traceback (most recent call last):
  File "./argParseOpts.py", line 32, in <module>
    try: sys.exit(main())
  File "./argParseOpts.py", line 21, in main
    if args.proj:
AttributeError: 'Namespace' object has no attribute 'proj'

当您提供-p时,args.comp会返回相同的错误(除了您先检查proj)。

我喜欢在交互式shell中测试这样的问题(例如IPython)。在那里,我可以输入您的parser定义,并发出如下命令:

In [35]: parser.parse_args(['-p'])
Out[35]: Namespace(proj='all')

In [36]: parser.parse_args(['-c'])
Out[36]: Namespace(comp='all')

In [37]: parser.parse_args(['-c','test'])
Out[37]: Namespace(comp='test')

显而易见,只设置了一个属性。