Argparse和几个独家论点

时间:2015-10-29 23:38:54

标签: python argparse

我正在尝试在python中实现Caesar密码,我正在使用argparse来解析参数。

但是我不知道如何创建这样的几个独占参数:

caesar.py        ,-   '-b'
                /
    '-d' --- xor
   /            \
 xor             `-   '-k key'
   \
    '-e' ---  '-k key'
  1. 您必须指定-d-e(不包括)。

  2. 如果您指定-e,则必须指定-k-b被禁止。

  3. 如果您指定-d,则必须指定-k-b(不包括)。

  4. 这是我做的:

    parser = argparse.ArgumentParser(description="Caesar Cipher")
    
    parser.add_argument("text", nargs="?", help="message to encode/decode")
    
    parser_code = parser.add_mutually_exclusive_group(required=True)
    parser_code.add_argument("-e", action="store_true", help="encode")
    parser_code.add_argument("-d", action="store_true", help="decode")
    
    parser_decode = parser.add_mutually_exclusive_group(required=True)
    parser_decode.add_argument('-k', type=int, dest="key",   help="key to use")
    parser_decode.add_argument('-b', action="store_true" help="bruteforce the key")
    
    args = parser.parse_args()
    

    实际上,它不起作用。的确,我仍然可以使用:

    python caesar.py -e -b message
    

    选项-b应该毫无意义。我知道我可以简单地进行检查并调用parser.print_help(),但是我希望在解析期间进行此检查,例如独占检查。

2 个答案:

答案 0 :(得分:1)

我认为argparse没有任何条款允许你的情况。我能想到的最好的是使用子解析器:

caesar.py:

import argparse

if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    actions = parser.add_subparsers(dest='action')

    encode_parser = actions.add_parser('encode')
    encode_parser.add_argument('-k', type=int, dest="key", help="key to use")

    decode_parser = actions.add_parser('decode')
    decode_parser.add_argument('-k', type=int, dest="key", help="key to use")
    decode_parser.add_argument('-b', dest='bruce_force', action='store_true')

    print parser.parse_args()

示例用法:

./caesar.py encode -k 5
./caesar.py decode -k 9 -b

答案 1 :(得分:0)

良好的编程设计是否使argparse做了一些它没有设计的事情?

您已经定义了两个互斥的参数组,实际上是对其出现的xor测试。但是argparse没有实现嵌套。我认为你可以将这两个群体放在另一个互斥的群体中,但净效应是将所有论点放在一个大群体中 - 即只允许整个群体中的一个。

我已经在bug /问题中探讨了实现嵌套的想法,以及可以实现任何类型的逻辑关系的组(xor,或(= any)和(= all)。但它是一个复杂的加法其中一个更麻烦的方面是在使用显示中格式化嵌套关系。简单的互斥组很乱。

您如何向您的用户解释允许哪些参数组合?

我认为你最好的选择是明智地定义默认值,这样你就可以清楚地告诉我们已经给出了哪些参数,以及哪些参数已经解析,然后在解析后执行测试。

对于' store_true'参数你可以只测试命名空间属性的真值。对于存储值的那些,测试is None通常是一个很好的指标。您的用户无法提供None值,因此args.dest is None显然意味着未使用该参数。

这只是编写嵌套if测试的问题:

if args.one and args.two is None:
    if args.three is not None:
        parser.error('three cannot occur with one and two')
etc.

argparse最好被看作是一个解析器 - 能够找出用户想要的东西。您可以使用argparse执行一些简单的测试,并在某些参数组合不兼容时通知用户。但它不应该是测试和使用参数的主要工具。您自己的代码应该对此负有最终责任。