【问题标题】:Argparse: defaults from fileargparse:来自文件的默认值
【发布时间】:2018-01-31 09:23:24
【问题描述】:

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

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

但我不想为 30 个参数这样做。 有什么简单的方法可以从 cmd 行获取可选参数,并默认为 config 文件?

【问题讨论】:

标签: python argparse configparser


【解决方案1】:

尝试以下操作,使用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'}

【讨论】:

  • 使用default=argparse.SUPPRESS,您将不需要None 过滤器。
【解决方案2】:

您可以使用来自collections 模块的ChainMap

来自文档:

ChainMap 将多个 dicts 或 其他映射一起创建一个单一的、可更新的视图。 [...]

查找连续搜索底层映射,直到一个键 成立。 [...]

所以,你可以创建

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

然后,创建一个 ChainMap:

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

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

【讨论】:

    【解决方案3】:

    您可以使用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)
    

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

    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)
    

    【讨论】:

      猜你喜欢
      • 2022-08-05
      • 1970-01-01
      • 2019-11-20
      • 2022-01-25
      • 1970-01-01
      • 1970-01-01
      • 2014-12-07
      • 1970-01-01
      相关资源
      最近更新 更多