2021年9月

[toc]

简单说一下

工作需要 需要批量修改很多机器上的配置文件,当然,只需要修改一行

配置文件格式为ini 每台机器上的配置文件都不一样,但是一定会有自己需要的那一行

这个时候,肯定会有很多人说,”这不简单吗,readline然后再判断是否包含,然后在修改就行了“

是的,问题的确就是这样做的话未免有些不雅观,都用python,那肯定要找一找有没有读取修改ini这种配置文件的python的库,最好还是python自带的,否则装库也麻烦

假设要修改的ini

[TEST1]
;; 这是注释
TEST_OPT_1 = 1
;; 这也是一处注释
TEST_OPT_2 = dotest
OPT_PATH = /home/auser 

[LISTEN]
;; 只监听本机ip
BIND_IP = 127.0.0.1
;; 监听端口
BIND_PORT = 80
MAX_FDS = 102400
SWITCH_USER = webserver

需要修改LISTEN节的BIND_PORT这个item,将其改为BIND_IP = 8080

库 ConfigParser

服务器是2.6.6 本地是2.7.x 具体忘了,但也正因此埋下了坑 坑后面说

import ConfigParser
import os
import shutil
try:
    from collections import OrderedDict as _default_dict
except ImportError:
    # fallback for setup.py which hasn't yet built _collections
    _default_dict = dict
    
class myconf(ConfigParser.ConfigParser):
    def __init__(self, defaults=None, dict_type=_default_dict,
                 allow_no_value=False):
        ConfigParserLib.ConfigParser.__init__(self,defaults, dict_type,
                 allow_no_value)

    # 这里重写了optionxform方法,直接返回选项名
    def optionxform(self, optionstr):
        return optionstr
def replaceText(path,aim,replace):
    lines = open(path).readlines()
    fp = open(path,'w')
    for s in lines:
        fp.write( s.replace(aim,replace))
    fp.close()
    
currPath = os.path.dirname(os.path.realpath(__file__))
configPath = os.path.join(currPath,"file/test.ini")
backConfigPath = os.path.join(currPath,"file/test.ini.bak")

shutil.copyfile(configPath,backConfigPath)

g_aim = ";"
g_replace = "@"
replaceText(configPath,g_aim,g_replace)

config = myconf()
config.read(configPath)
config.set('LISTEN',"BIND_PORT","8080")
config.write(open(configPath,"w"))
replaceText(configPath,g_replace,g_aim)

print "success"

这是我的替换代码

版本差异 tip

避免了很多的坑 ,但还是出问题了 服务器环境2.6.6 ConfigParser 没有allow_no_value这个属性,起作用是解析无意义的符号

慢慢来缕一缕

保存为小写问题

有人会发现 我是将ConfigParser重载了来使用的,其中,我重载了optionxform方法,因为原本的这个方法是这样的

def optionxform(self, optionstr):
    return optionstr.lower()

为了体现读取配置ini时候的大小写不敏感,python再读取对应内容的时候,都将其小写了,无论本来的内容是大写的也好,小写的也罢,都会变成小写的

于是 你使用这个玩意读取出来再存回去的配置全都会变成小写的,简直离谱

保留注释

接着 我自定义了一个replaceText方法,为什么要用替换方法来替换原本文件的内容呢?

替换的目标是;替换成@

;是ini之中的注释,因为程序是不读取注释的,没错,通过这个库,你重新生成的配置是没有一丝丝注释的——我感觉我拿脚本把所有的配置文件都跑一遍的话,会被骂死~

于是我就开始搜寻,发现需要先把注释替换为别的字符,然后开启allow_no_value=True默认值是False,这样 程序就会读取注释了,再在生成的内容中将@替换为;,我们的注释就保留成功了

真 版本差异问题探讨

前面说了 版本问题很重要

那么该怎么办呢?

个人做法---把2.7的库掏出来

在2.6的python下 用我捞出来的库 当然,记得改名称,不然就导标准库去了

相关链接

关于python:使用ConfigParser将注释写入文件

python自带的configparser模块解析ini文件