gpt4 book ai didi

python - 找出哪些参数在 argparse 中显式传递

转载 作者:太空宇宙 更新时间:2023-11-03 20:13:29 25 4
gpt4 key购买 nike

我需要处理两种配置应用程序的方法。一种是通过命令行参数,另一种是来自 JSON 文件(实际上,JSON 文件是存储上次运行的参数的结果)。

我可以通过合并两个命名空间对象来处理这个问题,如下所示:

cli_args = some_parser.parse_args()
with open(json_file, 'r') as f:
json_args = json.load(f)
all_args = argparse.Namespace()
all_args.__dict__ = {**vars(cli_args), **json_args}
# or all_args.__dict__ = {**json_args, **vars(cli_args)}

问题出在最后一行。如果我选择第一个版本,则 JSON 文件中的参数优先。如果我选择第二个版本,则 CLI 中的参数优先。

我希望 CLI 参数优先,但仅如果它们确实被指定。当解析器接受默认值时就会出现问题。在这种情况下,cli_args 对象将填充默认值,并且该值优先于 JSON 参数。

举一个简单的例子,让我看一下这个解析器:

parser = argparse.ArgumentParser()
parser.add_argument('--foo', default='FOO')
parser.add_argument('--bar', default='BAR')

假设我有一个 JSON 文件

{
"foo": "myfoo",
"bar": "mybar"
}

并且我使用 python myapp.py --foo hello 调用我的应用程序。

我想获得一个具有 foo=hello, bar=mybar 的命名空间对象。两种合并论点的方法都会给出不同的结果。首先,如果我给予 JSON 文件优先权,我将获得 foo=myfoo, bar=mybar。如果我给予 CLI 优先权,我会得到 foo=hello, bar=BAR

问题是我无法找到一种方法来区分从 parser.parse_args() 返回的命名空间中哪些参数是由用户填充的,以及哪些参数是使用默认设置填充的。

有没有办法询问 argparse 哪些参数实际上是在命令行上显式设置的,而不是填充默认值?

最佳答案

对于这里寻找此问题解决方案的下一个人,我们可以使用 Andrea 的解决方法和哨兵来准确找出显式传递的参数。

正如 Andrea 指出的,如果我们将命名空间传递给 parse_args(),则命名空间中的任何现有名称都会覆盖解析器的默认值。因此,如果我们使用包含所有参数名称的命名空间,那么解析后任何已更改其值的参数都必须已被显式参数更改。

我们需要将该命名空间中的所有内容设置为与解析器可能使用的默认值不同的内容。解析器的默认值很可能是None,所以这是行不通的;相反,我们需要一个哨兵对象。

import argparse
from argparse import Namespace

# Create a sentinel.
# Could use sentinel = object() instead; this way makes it clear
# if we ever print it that the object is a sentinel.
class _Sentinel:
pass
sentinel = _Sentinel()

parser = argparse.ArgumentParser()
parser.add_argument('--foo', type=int, default=10)
args = parser.parse_args()

# Make a copy of args where everything is the sentinel.
sentinel_ns = Namespace(**{key:sentinel for key in vars(args)})
parser.parse_args(namespace=sentinel_ns)

# Now everything in sentinel_ns that is still the sentinel was not explicitly passed.
explicit = Namespace(**{key:(value is not sentinel)
for key, value in vars(sentinel_ns).items()})

print("args.foo:", args.foo)
print("explicit.foo:", explicit.foo)

不带参数运行此脚本将打印

args.foo: 10
explicit.foo: False

使用 --foo 10 运行此脚本将打印

args.foo: 10
explicit.foo: True

关于python - 找出哪些参数在 argparse 中显式传递,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58594956/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com