首页 > 解决方案 > 如何在顶层和子命令之间共享参数

问题描述

在使用argparsewith 子命令的程序中,我想添加参数来控制详细程度。我希望这些充当“全局”参数,这意味着它们是在子命令之前还是之后传递都无关紧要。换句话说,我希望以相同的方式解释以下调用:

> ./test.py -v -v foo
> ./test.py foo -v -v
> ./test.py -v foo -v

我尝试过的事情

将参数添加到父解析器和子命令解析器:

main = arg.ArgumentParser()
main.add_argument ("-v", "--verbose", default = 0, action = "count")
s = main.add_subparsers()
foo = s.add_parser ("foo")
foo.add_argument ("-v", "--verbose", default = 0, action = "count")

print (main.parse_args().verbose)

这给出(都应该是 2):

调用 结果
./test.py -v -v foo 0
./test.py foo -v -v 2
./test.py -v foo -v 1

向主和子命令解析器添加一个通用的“父”解析器:

这个问题的启发,不同之处在于在另一个问题中一次只有一个子命令处于活动状态,而这里的主解析器和子命令解析器同时处于活动状态。

p = arg.ArgumentParser (add_help = False)
p.add_argument ("-v", "--verbose", default = 0, action = "count")
main = arg.ArgumentParser (parents = [ p ])
s = main.add_subparsers()
foo = s.add_parser ("foo", parents = [ p ])

print (main.parse_args().verbose)

这给出了与上面相同的结果。

将主解析器声明为子命令解析器的父级:

main = arg.ArgumentParser()
main.add_argument ("-v", "--verbose", default = 0, action = "count")
s = main.add_subparsers()
foo = s.add_parser ("foo", parents = [ main ], add_help = False)

print (main.parse_args().verbose)

foo这导致子命令期望自身的无限递归:

> ./test.py -v -v foo
usage: test.py foo [-h] [-v] {foo} ...
test.py foo: error: too few arguments

将参数添加到具有不同目的地的父和子命令解析器:

main = arg.ArgumentParser()
main.add_argument ("-v", "--verbose", default = 0, action = "count", dest = "main_verbose")
s = main.add_subparsers()
foo = s.add_parser ("foo")
foo.add_argument ("-v", "--verbose", default = 0, action = "count")

args = main.parse_args()
print (args.main_verbose + args.verbose)

这行得通,但它增加了复杂性:现在我需要组合每个公共参数的值以及与嵌套子命令一样多的层。

有没有办法定义“全局”参数,无论它们放在命令行的哪个位置,它的作用都是一样的?

标签: pythonargparse

解决方案


主解析器和子解析器不“共享”参数。每个都是一个独立的解析器,有自己的参数列表。该parents机制只是将参数定义(通过引用)从父级复制到子级。它不会改变解析。

主解析器将值放在其名称空间中,直到调用子解析器为止。子解析器做它的事情,解析剩余的字符串并将值放在它自己的命名空间中。完成后,子解析器命名空间被复制到主命名空间。

结果是对于任何带有 commondest的参数,子解析器的值(包括默认值)会覆盖 main 的值。因此,如果您想查看主要设置的内容,则可以使用不同的dest.


推荐阅读