如何解决CommentedMap.update() 不保留评论
我不确定我是否从正确的角度解决了这个问题,所以如果你看到另一种方式,请告诉我。
使用 ruamel.yaml 模块,我想在将一些配置文件转储回来并保留其注释之前得到一些配置文件的表示。
为此,我基本上有:
#!/usr/bin/env python3.5
from ruamel.yaml import YAML
class MyYaml():
def __init__(self,cm):
self.yaml = YAML()
self.yaml.default_flow_style = False
self.cm = cm
def load_main_config_file(self,path):
if isinstance(path,str):
with open(path,'r') as config_file:
self.cm.update(self.yaml.load(config_file))
# cannot be self.cm = self.yaml.load(config_file)
# because it would change the id of self.cm
# the dict would not be accessible from outside anymore
def load_config_file(self,path_key_list,target_dict = None):
for file_path,key_list in path_key_list:
with open(file_path,'r') as config_file:
self.update_dict((target_dict if target_dict is not None else self.cm),key_list,self.yaml.load(config_file))
def update_dict(self,my_dict,value):
"""
Works fine to preserve comments but cannot be used for the main config file as the dict is empty
"""
for k in key_list[:-1]:
my_dict = my_dict.setdefault(k,{})
my_dict[key_list[-1]] = value
from ruamel.yaml.comments import CommentedMap
from copy import deepcopy
class Parent():
def __init__(self):
self.__cm = CommentedMap() # private so users cannot modify
self.Yaml = MyYaml(self.__cm)
@property
def cm(self):
return deepcopy(self.__cm)
from ruamel.yaml import YAML
import sys
class Child(Parent):
def __init__(self):
super().__init__()
yaml = YAML()
self.Yaml.load_main_config_file("path_to_file")
print("\n\n############################")
print("Main load : ")
print("############################")
yaml.dump(self.cm,sys.stdout)
print("\n\n############################")
print("Other load :")
print("############################")
self.Yaml.load_config_file([("path_to_file",["other_file"])])
yaml.dump(self.cm,sys.stdout)
if __name__ == "__main__":
ch = Child()
我得到这个输出:
############################
Main load :
############################
key1: val1
key2: val2
key3:
key31: val31
key32: val32
key4:
key41: val41
############################
Other load :
############################
key1: val1
key2: val2
key3:
key31: val31
key32: val32
key4:
key41: val41
other_file:
############
# ! TEST ! #
############
key1: val1
# Comment 1
key2: val2
#this is a comment
key3:
key31: val31
key32: val32
key4:
key41: val41
PS:这是我在这里的第一篇文章,我希望它足够清楚。感谢您的时间!
解决方法
上线:
self.cm.update(self.yaml.load(config_file))
load()
返回一个 CommentedMap()
,从中更新只使用密钥
值对。如果您想复制评论,请执行以下操作:
tmp_cm = self.yaml.load(config_file)
self.cm.update(tmp_cm)
tmp_cm.copy_attributes(self.cm)
如果你想在 self.cm 上保留任何已经存在的注释,对于键
不会更新,您应该检查 .ca
属性并执行
更新相关项目,而不是完全覆盖评论。
请注意,此“内部数据”不保证保持稳定, 因此,请固定您的 ruamel.yaml 版本,并在更改该版本之前进行测试。 您还应该考虑更新您的 Python 版本,因为 3.5 是 EOL 并且 ruamel.yaml 中的支持将随着下一个次要版本升级而下降。
完整程序:
import sys
from ruamel.yaml import YAML
class MyYaml():
def __init__(self,cm):
self.yaml = YAML()
self.yaml.default_flow_style = False
self.cm = cm
def load_main_config_file(self,path):
if isinstance(path,str):
with open(path,'r') as config_file:
tmp_cm = self.yaml.load(config_file)
self.cm.update(tmp_cm)
tmp_cm.copy_attributes(self.cm)
# cannot be self.cm = self.yaml.load(config_file)
# because it would change the id of self.cm
# the dict would not be accessible from outside anymore
def load_config_file(self,path_key_list,target_dict = None):
for file_path,key_list in path_key_list:
with open(file_path,'r') as config_file:
self.update_dict((target_dict if target_dict is not None else self.cm),key_list,self.yaml.load(config_file))
def update_dict(self,my_dict,value):
"""
Works fine to preserve comments but cannot be used for the main config file as the dict is empty
"""
for k in key_list[:-1]:
my_dict = my_dict.setdefault(k,{})
my_dict[key_list[-1]] = value
from ruamel.yaml.comments import CommentedMap
from copy import deepcopy
class Parent():
def __init__(self):
self.__cm = CommentedMap() # private so users cannot modify
self.Yaml = MyYaml(self.__cm)
@property
def cm(self):
return deepcopy(self.__cm)
from ruamel.yaml import YAML
import sys
class Child(Parent):
def __init__(self):
super().__init__()
yaml = YAML()
self.Yaml.load_main_config_file("path_to_file")
print("\n\n############################")
print("Main load : ")
print("############################")
yaml.dump(self.cm,sys.stdout)
print("\n\n############################")
print("Other load :")
print("############################")
self.Yaml.load_config_file([("path_to_file",["other_file"])])
yaml.dump(self.cm,sys.stdout)
if __name__ == "__main__":
ch = Child()
给出:
############################
Main load :
############################
key1: val1
# Comment 1
key2: val2
#this is a comment
key3:
key31: val31
key32: val32
key4:
key41: val41
############################
Other load :
############################
key1: val1
# Comment 1
key2: val2
#this is a comment
key3:
key31: val31
key32: val32
key4:
key41: val41
other_file:
key1: val1
# Comment 1
key2: val2
#this is a comment
key3:
key31: val31
key32: val32
key4:
key41: val41
请注意,“嵌套”文件中的注释不会缩进,您 必须遍历各个评论并更改其开始列才能实现这一点。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。