悠闲博客-blog.yxrjt.cn

Python-configparser更新write保留注释

更新时间:2025-09-27 11:43点击:53

背景

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

AI运行代码


代码:


from configparser import ConfigParser

 

if __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)

AI运行代码

python


 结果:


[database]

host = localhost

port = 3307

username = my_user

password = my_password

 

[logging]

level = debug

output = log.txt

AI运行代码

python

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


解决办法

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


思路:

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


实现代码:

import os

from configparser import ConfigParser

from configparser import DEFAULTSECT

 

 

class MyConfigParser(configparser.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 cache
comment_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())
continue
value = 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_cache
comment_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_cache
comment_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 comments
with open(filename, encoding=encoding) as fp:
self._read_comments(fp)
except OSError:
continue
if isinstance(filename, os.PathLike):
filename = os.fspath(filename)
read_ok.append(filename)
return read_ok

def 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" % (configparser.DEFAULTSECT), [])
if comment_line:
fp.write("\n".join(comment_line) + "\n")
fp.write("[%s]\n" % configparser.DEFAULTSECT)
for (key, value) in self._defaults.items():
comment_line = self.comment_line_dict.get("%s.%s" % (configparser.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)

AI运行代码

python


结果:

# 数据库配置

[database]

# 主机

# IP

host = localhost

# 端口

port = 3307

# 用户名

username = my_user

# 密码

password = my_password

 

# 日志配置

[logging]

# 日志等级

level = debug

# 输出格式

output = log.txt

 

AI运行代码

python


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


原文链接:https://blog.csdn.net/qq_19446965/article/details/137481933

栏目分类

联系方式
  • help@yxrjt.cn
  • lgc@yxrjt.cn
  • admin@yxrjt.cn