Argparse:文件中的默认值

Argparse: defaults from file

我有一个需要很多参数的 Python 脚本。 我目前使用 configuration.ini 文件(使用 configparser 读取),但希望允许用户使用命令行覆盖特定参数。 如果我只有两个参数,我会使用类似的东西:

if not arg1:
    arg1 = config[section]['arg1']

但我不想对 30 个参数执行此操作。 从 cmd 行获取可选参数并默认为 config 文件的任何简单方法?

使用 dict.update() 尝试以下操作:

import argparse
import configparser

config = configparser.ConfigParser()
config.read('config.ini')
defaults = config['default']

parser = argparse.ArgumentParser()
parser.add_argument('-a', dest='arg1')
parser.add_argument('-b', dest='arg2')
parser.add_argument('-c', dest='arg3')
args = vars(parser.parse_args())

result = dict(defaults)
result.update({k: v for k, v in args.items() if v is not None})  # Update if v is not None

以ini文件为例:

[default]
arg1=val1
arg2=val2
arg3=val3

python myargparser.py -a "test"

result 将包含:

{'arg1': 'test', 'arg2': 'val2', 'arg3': 'val3'}

您可以使用 collections 模块中的 ChainMap

来自文档:

A ChainMap groups multiple dicts or other mappings together to create a single, updateable view. [...]

Lookups search the underlying mappings successively until a key is found. [...]

因此,您可以创建

  • 一个 config 包含配置文件中的键值对的字典,
  • a cmd_line_args 包含命令行中给出的字典

然后,创建一个ChainMap:

from collections import ChainMap
combined = ChainMap(cmd_line_args, config)

当你访问combined['arg1']时,首先会在cmd_line_args字典中查找arg1,如果没有找到,则返回config[arg1]。 您可以根据需要链接任意数量的字典,这样您就可以组合任意数量的默认级别。

您可以使用 parser.set_defaults() 来批量覆盖默认值(以便从配置中填充未输入的参数)。方便的是,这允许 argparse 参数默认字段为命令行或配置中未提供参数的情况指定最后的默认值。但是,参数仍然需要以某种方式添加到解析器中,以便解析器愿意识别它们。大多数情况下,如果您已经设置了 argparse 解析器,set_defaults() 很有用,但如果未在命令行中指定默认值,您只想覆盖来自配置的默认值:

import argparse

config = dict(
    a=11,
    b=13,
    c=19
)
parser = argparse.ArgumentParser()

#  add arguments to parser ...
parser.add_argument('-a', type=int)
parser.add_argument('-b', type=int)
parser.add_argument('-c', type=int)

parser.set_defaults(**config)
args = parser.parse_args()
print(args)

如果您不打算使用所有可用参数设置一个解析器,那么您也可以使用您的配置来设置一个(直接为每个参数提供默认值,因此无需执行额外的操作set_defaults() 步骤:

import argparse

parser = argparse.ArgumentParser()
config = dict(
    a=11,
    b=13,
    c=19
)

for key, value in config.items():
    parser.add_argument(f'-{key}', default=value, type=type(value))

args = parser.parse_args()
print(args)