CommentedMap.update() 不保留评论

如何解决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 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?