在 python 中获取参数并维护 argparse 解析器的状态

Fetch argument and maintain state of argparse parser in python

我正在尝试使用 python 中的 argparse 模块解析参数。我有两个相同实例的解析器对象——主解析器和辅助解析器。

使用辅助解析器解析的参数需要在 运行 时间挂钩到使用主解析器解析的参数,只有 运行 main parser.parseArgs 我才能成功() 一次。

我感兴趣的是获取使用辅助解析器解析的参数的值,然后将该参数传递给主解析器。我尝试 运行 辅助 parser.parseArgs() 但这会导致问题,因为 运行time 挂钩到主解析器失败。我想,我可能可以使用 argparse 中的命名空间对象来解决这个问题,但不知道该怎么做。有人可以帮忙吗?

    secondaryparser=argparse.ArgumentParser()
    secondaryparser.add_Argument('--c')
    args2= secondaryparser.parseArgs()
    print args2.c

    mainparser=argparse.ArgumentParser()
    mainparser.add_Argument('--a')
    mainparser.add_Argument('--b')
    args = mainparser.parseArgs()
    print args.a, args.b

据我了解,parseArgs() 会查看它自己的命名空间并弹出每个参数并清空堆栈,因此第二次 parseArgs() 调用失败。在这种情况下,我们如何保存辅助解析器的状态并将参数传递给主解析器。

这不完全是一个答案,但我无法将其放入评论中。我不确定您要做什么。如果不带参数调用 parser.parse_args,它将解析命令行。这将以您设置它的方式失败,因为参数 --a 和 --b 对于辅助解析器是未知的,而参数 --c 对于主解析器是未知的,因此它们不能同时解析同一个命令线.

您不能 运行 您向我们展示的代码,因为 ArgumentParser 没有名为 parseArgs 和 addArgument 的方法。 (他们是 parse_args 和 add_argument。)

您可以简单地通过将字符串作为参数传递给 parse_args 来使用 ArgumentParser 解析字符串,我想这对您的情况有效,但很难理解为什么您不能只一个参数为 --a、--b 和 --c 的解析器。我想你的实际应用一定比你给出的示例复杂得多。

我认为您关于弹出堆栈的评论不恰当,因为您有两个完全不同的解析器,具有不同的堆栈。我想你可以解析命令行两次,但由于解析器的定义本质上是相同的,它不会完成任何事情(或者至少,没有什么明显的。)

我不知道这是否有帮助。如果没有,也许您可​​以让我们更好地了解您需要做什么。

P.S。在复杂的情况下我总是做的是让一个名为 getArgs 的函数说,它根据需要获取所有参数处理它们,修改 ArgumentParser 返回的 args 对象,并 returns 它。举个简单的例子,假设我有一个名为 --extent 的字段,用户应该输入一个 30 到 100 之间的整数,但我希望它是小数。我的 getArgs 函数验证输入,然后执行 args.extent *= .01 和 returns args。

这是对您要执行的操作的猜测。我将明确地使用 sys.argv,所以很清楚发生了什么。

import sys
print sys.argv

secondaryparser=argparse.ArgumentParser()
secondaryparser.add_argument('--c')
args2, extras2 = secondaryparser.parse_known_args(sys.argv[1:])
print args2  # diagnositic display of the Namespace
print extras
print args2.c

mainparser=argparse.ArgumentParser()
mainparser.add_argument('--a')
mainparser.add_argument('--b')
args, extras = mainparser.parse_known_args(sys.argv[1:], args2)
# args = mainparser.parse_args(extras2, args2)
print args.a, args.b
print args2  # debug
print args   # debug
print extras

secondaryparser 设置为在命令行的参数列表中查找 --c。我正在使用 parse_known_args,因此如果您包含 --a--b,它不会引发错误。如果存在,这些字符串将出现在 extras2 列表中。

mainparser 可以用 mainparser.parse_args() 调用,但如果包含 --c 会引发错误。相反,我再次使用了 parse_known_args,或者传递给它 extras2,它已经删除了 --c

argsargs2 应该是这个调用后相同的命名空间,并且应该包含 abc 属性。

使用 parse_known_args 和命名空间参数,您可以链接多个解析器,所有解析器都使用相同的输入。 parse_known_args 的输出是您可以访问的唯一 'state' 解析 - 它是包含已解析字符串的命名空间,以及它无法处理的字符串列表。

解析器不是状态机。它是一个对象 (class ArgparseParser) 'owns' 多个参数(argparse.Action 对象)。 parse_args 是一种获取字符串列表的方法,returns 是一个命名空间对象。 parser 中的任何内容都不会因该调用而发生变化。 parse_args(或 parse_known_args)可以多次调用,在默认 sys.argv(但为什么?)或其他(测试)输入上重复调用。

测试代码通常如下所示:

 parser = argparer.ArguementParser(...)
 ....
 print (parser.parse_args([])) # to see how it behaves without any commandline values)
 print (parser.parse_args(['-f', 'foovalue'])
 args = parser.parse_args()
 print (args)
 parser.print_help()
 try:
     parser.parse_args(['bad','value'])
 except <capture error ans sys.exit>
     print (error)

我解决这个问题的方法是这样的。感谢 hpaulj 提供的方法。

known_args, unknown_args = secondaryparser.parse_known_args()
value_c = known_args.c 

finalargs = mainparser.parse_known_args(args=unknown_args, namespace=known_args)

使用parse_known_args,我能够预先获取"C"的值。如果您在这里看到第一段代码,我返回了一个包含已知和未知参数的元组。我使用 known_args.c 获取 "C" 的值,并将 unknown_Args 传递给 main_parser,命名空间为 "args"。这对我有用。