python-3.x - 使用 yaml 覆盖命名空间
问题描述
问题陈述
我希望 python 模块中支持的选项可以用.yaml
文件覆盖,因为在某些情况下,有太多选项需要用非默认值指定。
我实现的逻辑如下。
parser = argparse.ArgumentParser()
# some parser.add statements that comes with default values
parser.add_argument("--config_path", default=None, type=str,
help="A yaml file for overriding parameters specification in this module.")
args = parser.parse_args()
# Override parameters
if args.config_path is not None:
with open(args.config_path, "r") as f:
yml_config = yaml.safe_load(f)
for k, v in yml_config.items():
if k in args.__dict__:
args.__dict__[k] = v
else:
sys.stderr.write("Ignored unknown parameter {} in yaml.\n".format(k))
问题是,对于某些选项,我有特定的函数/lambda 表达式来转换输入字符串,例如:
parser.add_argument("--tokens", type=lambda x: x.split(","))
为了在 YAML 中解析选项规范时应用相应的功能,添加这么多if
语句似乎不是一个好的解决方案。当在对象中引入新选项时,维护一个相应更改的字典parser
似乎是多余的。是否有任何解决方案来获取对象type
中的每个参数parser
?
解决方案
如果您添加到解析器的元素以add_argument
开头,--
那么它们实际上是可选的,通常称为选项。你可以找到这些遍历实例_get_optonal_actions()
方法的结果。parser
如果你config.yaml
看起来像:
tokens: a,b,c
,那么你可以这样做:
import sys
import argparse
import ruamel.yaml
sys.argv[1:] = ['--config-path', 'config.yaml'] # simulate commandline
yaml = ruamel.yaml.YAML(typ='safe')
parser = argparse.ArgumentParser()
parser.add_argument("--config-path", default=None, type=str,
help="A yaml file for overriding parameters specification in this module.")
parser.add_argument("--tokens", type=lambda x: x.split(","))
args = parser.parse_args()
def find_option_type(key, parser):
for opt in parser._get_optional_actions():
if ('--' + key) in opt.option_strings:
return opt.type
raise ValueError
if args.config_path is not None:
with open(args.config_path, "r") as f:
yml_config = yaml.load(f)
for k, v in yml_config.items():
if k in args.__dict__:
typ = find_option_type(k, parser)
args.__dict__[k] = typ(v)
else:
sys.stderr.write("Ignored unknown parameter {} in yaml.\n".format(k))
print(args)
这使:
Namespace(config_path='config.yaml', tokens=['a', 'b', 'c'])
请注意:
- 我正在使用
ruamel.yaml
. 以这种方式加载实际上比使用更快,from ruamel import yaml; yaml.safe_load()
尽管您的配置文件可能不够大而无法注意到。 - 我正在使用
.yaml
官方常见问题解答中推荐的文件扩展名。你也应该这样做,除非你不能(例如,如果你的文件系统不允许这样做)。 - 我在选项字符串中使用破折号
--config-path
而不是下划线,这更自然地键入并自动转换为下划线以获取有效的标识符名称
您可能需要考虑另一种方法,sys.argv
手动
解析--config-path
,然后为 YAML 配置文件中的所有选项设置默认值,然后调用.parse_args()
. 按此顺序执行操作允许您在命令行上覆盖配置文件中具有值的内容。如果您按照自己的方式做事,则如果配置文件具有除一个以外的所有正确值,则始终必须编辑该配置文件。
推荐阅读
- c - C 中的 Tee 函数调用不起作用,也不是 tee 命令
- android - How to get document from "Firestore" using compound query in android
- excel - How to update the range in powerpoint chart from excel
- javascript - When user scrolls down to image position, execute transformation
- javascript - Concise way to get to final output from selenium webdriver promises
- php - 如何在不拒绝访问控制器的情况下使用 Symfony 4 Voters
- ios - 企业应用程序是否会在推送证书和/或配置文件到期/撤销时失效?
- java - AspectJ - 来自外部 JAR 的方面
- kubernetes - RabbitMQ 管理 - 加载队列或交换时出现 404
- javascript - 放弃更改并重置所有数据离子/角度