Python-configparser更新write保留注释

背景

python语言用来解析配置文件的模块是ConfigParser,python3中是configparser模块,在使用中经常用到write方法将配置项重新写入文件:

config.ini文件:

# 数据库配置
[database]
# 主机
# IP
host = localhost
# 端口
port = 3306
# 用户名
username = my_user
# 密码
password = my_password# 日志配置
[logging]
# 日志等级
level = debug
# 输出格式
output = log.txt

代码:

from configparser import ConfigParserif __name__ == '__main__':# 创建ConfigParser对象config = ConfigParser()# 读取配置文件config.read('config.ini', encoding='utf-8')# 在配置文件中修改某个配置项的值config.set('database', 'port', '3307')  # 修改port为3307# 写入配置文件,保留原有注释with open('config.ini', 'w', encoding='utf-8') as configfile:config.write(configfile)

 结果:

[database]
host = localhost
port = 3307
username = my_user
password = my_password[logging]
level = debug
output = log.txt

结果发现配置文件中的空行和注释行都会被去掉,虽然这个并不影响使用,但配置文件的可读性无疑还是变差了。 

解决办法

为此特地对ConfigParser模块进行了一点改动,使其保留注释项和空行。

思路

就是在读配置文件的时候碰到注释行或换行就缓存起来,然后在写入的时候从缓存中取出就可以了。

实现代码:

import os
from configparser import ConfigParser
from configparser import DEFAULTSECTclass MyConfigParser(ConfigParser):def __init__(self, *args, **kwargs):super().__init__(*args, **kwargs)self.comment_line_dict = {}def _read_comments(self, fp):"""read comments"""# comment or blank line temp cachecomment_line_cache = []sections = []for _, line in enumerate(fp):# comment or blank line?if line.strip() == '' or line[0] in self._comment_prefixes:comment_line_cache.append(line.strip())continuevalue = line.strip()# is it a section header?mo = self.SECTCRE.match(value)if mo:section_name = mo.group('header')self.comment_line_dict[section_name] = comment_line_cachecomment_line_cache = []sections.append(section_name)# an option line?else:mo = self._optcre.match(value)if mo:optname, vi, optval = mo.group('option', 'vi', 'value')optname = self.optionxform(optname.rstrip())self.comment_line_dict["%s.%s" % (sections[-1], optname)] = comment_line_cachecomment_line_cache = []def read(self, filenames, encoding=None):"""Rewrite the read method of the parent class"""if isinstance(filenames, (str, bytes, os.PathLike)):filenames = [filenames]read_ok = []for filename in filenames:try:with open(filename, encoding=encoding) as fp:self._read(fp, filename)# Add methods for reading commentswith open(filename, encoding=encoding) as fp:self._read_comments(fp)except OSError:continueif isinstance(filename, os.PathLike):filename = os.fspath(filename)read_ok.append(filename)return read_okdef write(self, fp, space_around_delimiters=True):"""Write an .ini-format representation of the configuration state."""if self._defaults:comment_line = self.comment_line_dict.get("%s" % (DEFAULTSECT), [])if comment_line:fp.write("\n".join(comment_line) + "\n")fp.write("[%s]\n" % DEFAULTSECT)for (key, value) in self._defaults.items():comment_line = self.comment_line_dict.get("%s.%s" % (DEFAULTSECT, key), [])if comment_line:fp.write("\n".join(comment_line) + "\n")fp.write("%s = %s\n" % (key, str(value).replace('\n', '\n\t')))fp.write("\n")for section in self._sections:comment_line = self.comment_line_dict.get("%s" % (section), [])if comment_line:fp.write("\n".join(comment_line) + "\n")fp.write("[%s]\n" % section)for (key, value) in self._sections[section].items():comment_line = self.comment_line_dict.get("%s.%s" % (section, key), [])if comment_line:fp.write("\n".join(comment_line) + "\n")if (value is not None) or (self._optcre == self.OPTCRE):key = " = ".join((key, str(value).replace('\n', '\n\t')))fp.write("%s\n" % (key))fp.write("\n")if __name__ == '__main__':# 创建ConfigParser对象# config = ConfigParser()config = MyConfigParser()# 读取配置文件config.read('config.ini', encoding='utf-8')# 在配置文件中修改某个配置项的值config.set('database', 'port', '3307')  # 修改port为3307# 写入配置文件,保留原有注释with open('config.ini', 'w', encoding='utf-8') as configfile:config.write(configfile)

结果:

# 数据库配置
[database]
# 主机
# IP
host = localhost
# 端口
port = 3307
# 用户名
username = my_user
# 密码
password = my_password# 日志配置
[logging]
# 日志等级
level = debug
# 输出格式
output = log.txt

实现的可能不太严谨,大家根据需要可以修改实现更有扩展性的功能。


参考:

Python 使用ConfigParser写入注释到文件中|极客教程

保留注释换行的python模块configparser 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/808324.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

从路由器syslog日志监控路由器流量

路由器是关键的网络基础设施组件,需要随时监控,定期监控路由器可以帮助管理员确保路由器通信正常。日常监控还可以清楚地显出通过网络的流量,通过分析路由器流量,安全管理员可及早识别可能发生的网络事件,从而避免停机…

关于STL容器线程安全性的问题

关于STL容器线程安全性的问题 STL容器(如vector)本身并不是线程安全的,因此在使用它们进行多线程编程时需要格外小心。即便写入操作(由生产者执行)是由单线程完成的,但在并发读取时,由于可能发…

程序员如何搞副业——中学生视角看职业拓展的深入探索

在数字化浪潮席卷全球的今天,程序员这一职业因其独特的魅力和广阔的发展前景而备受瞩目。作为一名中学生,虽然尚未步入职业领域,但提前了解程序员的副业之路,不仅可以帮助我们拓宽视野,还能为未来的职业规划提供有益的参考。 首先,个人项目开发是程序员搞副业的一个重要…

计算机中,逻辑端口

计算机中,端口是什么 在计算机领域中,端口(Port)是一个逻辑概念,用于标识计算机与外部设备或另一台计算机通信时的出入口。它是计算机与外部通信的途径,分为物理端口和逻辑端口两种。 物理端口:物理端口也被称为接口,是计算机主板上或其他设备上的硬件接口,如USB接口…

算法训练营第二十三天(二叉树完结)

算法训练营第二十三天(二叉树完结) 669. 修剪二叉搜索树 力扣题目链接(opens new window) 题目 给定一个二叉搜索树,同时给定最小边界L 和最大边界 R。通过修剪二叉搜索树,使得所有节点的值在[L, R]中 (R>L) 。你可能需要改…

SQLite数据库在Linux系统上的使用

SQLite是一个轻量级的数据库解决方案,它是一个嵌入式的数据库管理系统。SQLite的特点是无需独立的服务器进程,可以直接嵌入到使用它的应用程序中。由于其配置简单、支持跨平台、服务器零管理,以及不需要复杂的设置和操作,SQLite非…

【算法】排硬币 - 二分法/牛顿迭代

题目 假设有n枚硬币,要摆一个阶梯形,第一行1个,第二行2个,以此类推,看n枚硬币能摆多少行,返回行数。未摆满行的不算。 原理 二分法 先假设放 x 行需要 m 个硬币,用 m 与 n 对比,…

OpenGL着色器实现纹理合并显示

OpenGL着色器实现纹理合并显示 本文介绍了opengl下实现纹理的装载,同时借助顶点着色器和片源着色器实现两个不同外部纹理的合并显示。 目录 1 opengl下纹理的装载2 纹理合并效果显示3 完整的代码 1 opengl下纹理的装载 // 初始化GLFWif (!glfwInit()) {std::cerr …

从建表语句带你学习doris_数据类型

1、前言概述 1.1、doris建表模板 CREATE [EXTERNAL] TABLE [IF NOT EXISTS] [DATABASE.]table_name (column_definition1[,column_deinition2,......][,index_definition1,[,index_definition2,]] ) [ENGINE = [olap|mysql|broker|hive]] [key_desc] [COMMENT "table co…

共享低碳未来!科士达新一代工商业储能产品引爆ESIE 2024

4月11日,第十二届储能国际峰会暨展览会(ESIE 2024)在北京首钢会展中心盛大开幕,科士达以“数智光储,共享低碳未来”为主题,携多款工商业储能产品及解决方案惊艳亮相本次盛会。 展会首日,科士达展…

C/C++基础----运算符

算数运算符 运算符 描述 例子 两个数字相加 两个变量a b得到两个变量之和 - 两个数字相减 - * 两个数字相乘 - / 两个数字相除 - % 两个数字相除后取余数 8 % 3 2 -- 一个数字递减 变量a:a-- 、--a 一个数字递增 变量a: a 、 a 其中递…

VSCode中调试C++程序

目录 一、准备工作:安装插件 1、C/C插件 ​编辑 2、CMake插件 3、CMake tool插件 二、调试过程 1、debug 2、打断点 3、调C/C文件 每次重新调试的时候都忘了具体步骤,直接给自己写个备忘录好了。 一、准备工作:安装插件 1、C/C插件…

java二叉树前中后序遍历

代码随想录解题思路&#x1f192;力扣前序题目&#x1f192;力扣中序题目&#x1f192;力扣后序题目 递归遍历 // 前序遍历 class Solution {public List<Integer> preorderTraversal(TreeNode root) {List<Integer> res new ArrayList<>();preorder(root…

zabbix“专家坐诊”第236期问答

问题一 Q&#xff1a;我的trap里已经可以收到信息了&#xff0c;后续要怎么创建监控项呀&#xff1f; A&#xff1a;参考&#xff1a; 问题二 Q&#xff1a;snmp和snmp trap咋搞&#xff1f; A&#xff1a;你指的是如何开启这些协议还是如何做监控项&#xff1f; Q&#xff1…

Opentelemetry——Observability Primer

Observability Primer 可观测性入门 Core observability concepts. 可观测性核心概念。 What is Observability? 什么是可观测性&#xff1f; Observability lets us understand a system from the outside, by letting us ask questions about that system without know…

动态开辟字符串malloc

1. 定义一个指针 int *p; 直接给指针赋值会产生段错误 &#xff1a;*p c malloc 函数原型 void *malloc(size_t size) &#xff08;开辟的内容大小&#xff09; C库函数 void *malloc(size_t size)分配所需的内存空间&#xff0c;并返回一个指向它的指针。 作用&…

Java——数组练习

目录 一.数组转字符串 二.数组拷贝 三.求数组中元素的平均值 四.查找数组中指定元素(顺序查找) 五.查找数组中指定元素(二分查找) 六.数组排序(冒泡排序) 七.数组逆序 一.数组转字符串 代码示例&#xff1a; import java.util.Arrays int[] arr {1,2,3,4,5,6}; String…

数据分析——数据规范化

数据规范化是数据分析中的一个重要步骤&#xff0c;其目的在于确保数据的一致性和可比性&#xff0c;提高数据质量和分析结果的准确性。以下是一些数据规范化的常见方法和技术&#xff1a; 数据清洗&#xff1a;此步骤主要清除数据中的重复项、空格、格式错误等&#xff0c;确…

【二分与前缀和】python例题详解

文章目录 1、数的范围 2、数的三次方根 3、前缀和 4、子矩阵的和 5、机器人跳跃问题 1、数的范围 题目 给定一个按照升序排列的长度为 n 的整数数组&#xff0c;以及 q 个查询。对于每个查询&#xff0c;返回一个元素 k的起始位置和终止位置&#xff08;位置从 00 开始计…

批归一化(BN)在神经网络中的作用与原理

文章目录 1. 批归一化&#xff08;BN&#xff09;在神经网络中的作用与原理1.1 作用与优势1.2 原理与推导 2. 将BN应用于神经网络的方法2.1 训练时的BN 2. 将BN应用于神经网络的方法2.1 训练时的BN2.2 测试时的BN代码示例&#xff08;Python&#xff09;&#xff1a; 3. BN的优…