Argparse:如果存在'x',则必需参数'y'

asu*_*hak 94 python argparse

我有如下要求:

./xyifier --prox --lport lport --rport rport
Run Code Online (Sandbox Code Playgroud)

对于参数prox,我使用action ='store_true'来检查它是否存在.我不要求任何论据.但是,如果设置了--prox,我也需要 rport和lport.有没有一种简单的方法可以使用argparse执行此操作而无需编写自定义条件编码.

更多代码:

non_int.add_argument('--prox', action='store_true', help='Flag to turn on proxy')
non_int.add_argument('--lport', type=int, help='Listen Port.')
non_int.add_argument('--rport', type=int, help='Proxy port.')
Run Code Online (Sandbox Code Playgroud)

bor*_*ing 94

不,argparse中没有任何选项可以制作相互包含的选项集.

处理这个问题最简单的方法是:

if args.prox and (args.lport is None or args.rport is None):
    parser.error("--prox requires --lport and --rport.")
Run Code Online (Sandbox Code Playgroud)

  • 谢谢你的`parser.error`方法,这就是我想要的! (15认同)
  • 你不应该使用'或'吗?毕竟你需要两个args`如果args.prox和(args.lport是None或args.rport是None): (7认同)
  • 这会阻止你将`--lport`或`--rport`设置为`0`,这可能是程序的有效输入. (6认同)
  • 那就是我最终要做的 (2认同)
  • 除了 `args.lport is None`,您可以简单地使用 `not args.lport`。我认为它更像pythonic。 (2认同)
  • “parser”对象是 [argparse.ArgumentParser](https://docs.python.org/3/library/argparse.html#argumentparser-objects) 的实例。 (2认同)

Mir*_*ira 47

你在谈论有条件要求的论点.就像@borntyping说你可以检查错误并执行parser.error(),或者你可以只应用与--prox添加新参数时相关的要求.

您的示例的简单解决方案可能是:

non_int.add_argument('--prox', action='store_true', help='Flag to turn on proxy')
non_int.add_argument('--lport', required='--prox' in sys.argv, type=int)
non_int.add_argument('--rport', required='--prox' in sys.argv, type=int)
Run Code Online (Sandbox Code Playgroud)

这种方式required接收TrueFalse取决于用户是否使用--prox.这也保证了-lport-rport相互之间的独立行为.

  • 请注意,`ArgumentParser`可用于解析除`sys.argv`以外的列表中的参数,这种情况会失败. (6认同)
  • 如果使用 `--prox=<value>` 语法,这也会失败。 (2认同)
  • 然后`required='--prox' in " ".join(sys.argv)` (2认同)

Adi*_*ram 7

如果存在,如何使用parser.parse_known_args()method然后添加args --lport--rportargs --prox

# just add --prox arg now
non_int = argparse.ArgumentParser(description="stackoverflow question", 
                                  usage="%(prog)s [-h] [--prox --lport port --rport port]")
non_int.add_argument('--prox', action='store_true', 
                     help='Flag to turn on proxy, requires additional args lport and rport')
opts, rem_args = non_int.parse_known_args()
if opts.prox:
    non_int.add_argument('--lport', required=True, type=int, help='Listen Port.')
    non_int.add_argument('--rport', required=True, type=int, help='Proxy port.')
    # use options and namespace from first parsing
    non_int.parse_args(rem_args, namespace = opts)
Run Code Online (Sandbox Code Playgroud)

还要记住,您可以提供opts第一次解析后生成的名称空间,而第二次解析其余参数。这样,最后,在完成所有解析之后,您将拥有一个包含所有选项的名称空间。

缺点:

  • 如果--prox不存在,则命名空间中甚至不存在其他两个从属选项。尽管根据您的用例(如果--prox不存在),其他选项发生的情况无关紧要。
  • 需要修改用法消息,因为解析器不知道完整结构
  • --lport并且--rport不显示在帮助消息中


hpa*_*ulj 5

你没有设置lport时使用吗?prox如果不是,为什么不lportrport的争论prox?例如

parser.add_argument('--prox', nargs=2, type=int, help='Prox: listen and proxy ports')
Run Code Online (Sandbox Code Playgroud)

这可以节省您的用户输入.它和测试if args.prox is not None:一样容易if args.prox:.

  • 为了示例的完整性,当您的 nargs > 1 时,您将在解析的参数等中获得一个列表,您可以按照通常的方式处理这些列表。例如,`a,b = args.prox`、`a = args.prox[0]` 等。 (2认同)