通过Python编辑配置文件

15 投票
2 回答
23131 浏览
提问于 2025-04-16 13:39

我需要通过Python来编辑一个配置文件,我在StackOverflow和谷歌上搜索过,但没有找到适合我情况的解决方案,因为我需要替换文件中的多行内容,并且在搜索时要进行匹配。

我找到的内容主要是讲如何替换一行,但我至少需要替换8行,我想知道有没有比把10个replace(foo, bar)放在一起更简洁优雅的方法。

我需要“匹配”像“ENABLEPRINTER”、“PRINTERLIST”、“PRNT1.PORT”这样的行。我想匹配这些文本,并忽略后面的内容(例如:“=PRNT1, PRNT2”)。

所以我会做类似这样的事情:

replace('ENABLEPRINTER', 'y')
replace('PRINTERLIST', 'PRNT3) 

文件的内容看起来是这样的:

ENABLEPRINTER=n
PRINTERLIST=PRNT1, PRNT2

PRNT1.PORT=9600
PRNT1.BITS=8

另外,这些文件大约有100行,我需要编辑其中大约10行。

非常感谢你的帮助。

更新

使用@J.F. Sebastian发布的代码后,我现在遇到了以下错误:

configobj.ParseError: Parse error in value at line 611.

文件的第611行是:

log4j.appender.dailyRollingFile.DatePattern='.'yyyy-MM-d

所以问题出在'这个字符上。

如果我把那一行注释掉,使用@J.F. Sebastian发布的代码脚本就能正常工作。

2 个回答

5

如果文件是 java.util.Properties 格式的话,你可以使用 pyjavaproperties 来处理它:

from pyjavaproperties import Properties

p = Properties()
p.load(open('input.properties'))

for name, value in [('ENABLEPRINTER', 'y'), ('PRINTERLIST', 'PRNT3')]:
    p[name] = value
p.store(open('output.properties', 'w'))

这个工具不是特别稳定,但一些修复可以帮助后面的人更好地使用。


如果你想在一个短字符串中多次替换内容:

for old, new in [('ENABLEPRINTER', 'y'), ('PRINTERLIST', 'PRNT3')]:
    some_string = some_string.replace(old, new)

如果你想在配置文件中替换变量名(使用 configobj 模块):

import configobj

conf = configobj.ConfigObj('test.conf')

for old, new in [('ENABLEPRINTER', 'y'), ('PRINTERLIST', 'PRNT3')]:
    conf[new] = conf[old]
    del conf[old]
conf.write()

如果你说的 replace('ENABLEPRINTER', 'y') 是指把 y 赋值给 ENABLEPRINTER 变量,那么:

import configobj

ENCODING='utf-8'
conf = configobj.ConfigObj('test.conf', raise_errors=True,
    file_error=True,           # don't create file if it doesn't exist
    encoding=ENCODING,         # used to read/write file
    default_encoding=ENCODING) # str -> unicode internally (useful on Python2.x)

conf.update(dict(ENABLEPRINTER='y', PRINTERLIST='PRNT3'))
conf.write()

看起来 configobj 和以下内容不兼容:

name = '.'something

你可以给它加上引号:

name = "'.'something"

或者:

name = '.something'

或者

name = .something

conf.update() 做的事情类似于:

for name, value in [('ENABLEPRINTER', 'y'), ('PRINTERLIST', 'PRNT3')]:
    conf[name] = value
7
import re 
pat = re.compile('ENABLEPRINTER|PRINTERLIST|PRNT1.PORT')

def jojo(mat,dic = {'ENABLEPRINTER':'y',
                    'PRINTERLIST':'PRNT3',
                    'PRNT1.PORT':'734'} ):
    return dic[mat.group()]

with open('configfile','rb+') as f:
    content = f.read()
    f.seek(0,0)
    f.write(pat.sub(jojo,content))
    f.truncate()

之前:

ENABLEPRINTER=n 
PRINTERLIST=PRNT1, PRNT2  

PRNT1.PORT=9600 
PRNT1.BITS=8

之后:

y=n 
PRNT3==PRNT1, PRNT2  

734=9600
PRNT1.BITS=8

这太简单了,不能算是一个完整的答案。请说说有哪些错误或不足之处。

正则表达式的好处在于它们可以很容易地根据特定情况进行调整。

.

编辑:

我刚刚看到:

"我想做的是给变量赋一个新值"

你早些时候就可以提到这一点的!

能否给一个文件的例子,展示一下修改前和修改后的内容?

.

编辑 2

这是用来更改文件中某些变量值的代码:

import re
from os import fsync

def updating(filename,dico):

    RE = '(('+'|'.join(dico.keys())+')\s*=)[^\r\n]*?(\r?\n|\r)'
    pat = re.compile(RE)

    def jojo(mat,dic = dico ):
        return dic[mat.group(2)].join(mat.group(1,3))

    with open(filename,'rb') as f:
        content = f.read() 

    with open(filename,'wb') as f:
        f.write(pat.sub(jojo,content))



#-----------------------------------------------------------

vars = ['ENABLEPRINTER','PRINTERLIST','PRNT1.PORT']
new_values = ['y','PRNT3','8310']
what_to_change = dict(zip(vars,new_values))


updating('configfile_1.txt',what_to_change)

之前:

ENABLEPRINTER=n 
PRINTERLIST=PRNT1, PRNT2  

PRNT1.PORT=9600 
PRNT1.BITS=8

之后:

ENABLEPRINTER=y 
PRINTERLIST=PRNT3

PRNT1.PORT=8310 
PRNT1.BITS=8

撰写回答