16

I need to edit a configuration file through python and i tried searching on stackoverflow and google and they don't cover my situation, since i need to replace lines in the file and perform matches in my search.

Also, what i found covers how to do it for one line, i will be performing at least 8 line replacements in the file and I would like to know if there is a cleaner and more elegant way of doing this than putting 10 replace(foo, bar) lines altogether.

I need to "match" lines like "ENABLEPRINTER", "PRINTERLIST", "PRNT1.PORT". I want to match thesse text and ignore whatever follows (ex: "=PRNT1, PRNT2").

So i would do something like

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

The file looks like this:

ENABLEPRINTER=n
PRINTERLIST=PRNT1, PRNT2

PRNT1.PORT=9600
PRNT1.BITS=8

Also note these files are about 100 lines and i need to edit about 10 of them.

Thank you very much for your help.

UPDATE:

Using the code posted by @J.F. Sebastian, i'm now getting the following error:

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

Line 611 of the file is:

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

So the problem is with the ' character.

If I comment out that line, the script is working fine with the code posted by @J.F. Sebastian.

2 Answers 2

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()

Before:

ENABLEPRINTER=n 
PRINTERLIST=PRNT1, PRNT2  

PRNT1.PORT=9600 
PRNT1.BITS=8

After:

y=n 
PRNT3==PRNT1, PRNT2  

734=9600
PRNT1.BITS=8

Too simple to be definitive. Say what are the errors or weaknesses.

The advantage of regexes is they can be modulated easily to particular cases.

.

EDIT:

I've just seen that:

"what i want to do is assign a new value to the variable "

you could inform of that earlier !

Could you give an exemple of file before / after , please.

.

EDIT 2

Here's the code to change the values of certain variables in a file:

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)

Before:

ENABLEPRINTER=n 
PRINTERLIST=PRNT1, PRNT2  

PRNT1.PORT=9600 
PRNT1.BITS=8

After:

ENABLEPRINTER=y 
PRINTERLIST=PRNT3

PRNT1.PORT=8310 
PRNT1.BITS=8
Sign up to request clarification or add additional context in comments.

5 Comments

Hi! Thank you for your very detailes answer! I'm sorry i created so much confusion with my question, i did a terrible job at explaining myself. The last code that you posted to change certain variables in a file isnt working for me.
I'm getting this error: Traceback (most recent call last): File "D:\script\editconf.py", line 26, in <module> updating('printer.properties',what_to_change) File "D:\script\editconf.py", line 16, in updating f.write(pat.sub(jojo,content)) TypeError: can't use a string pattern on a bytes-like object
@mstefan Are you with Python 3.x ?
@mstefan Try to define RE = b'(('+'|'.join(dico.keys())+')\s*=)[^\r\n]*?(\r?\n|\r)' or something like that. I am with Python 2.7 and I can't test. Maybe , since RE is an agregation, it has to be RE = b'((' + b'|'.join(dico.keys()) + b')\s*=)[^\r\n]*?(\r?\n|\r)' . Maybe the keys of dico must be made bytes too ?
There is a method using the "ConfigParser" to specifically change settings on python "ini" files. Although practical, totally changes the file by removing the comments and so I gave up for the method proposed here when we want to change python "ini" files! For more information see stackoverflow.com/questions/27964134/….
5

If the file is in java.util.Properties format then you could use 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'))

It is not very robust, but various fixes for it could benefit people who come next.


To replace multiple times in a short string:

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

To replace variables names in a configuration file (using configobj module):

import configobj

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

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

If by replace('ENABLEPRINTER', 'y') you mean assign y to the ENABLEPRINTER variable then:

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()

It seems configobj is not compatible with:

name = '.'something

You could quote it:

name = "'.'something"

Or:

name = '.something'

Or

name = .something

conf.update() does something similar to:

for name, value in [('ENABLEPRINTER', 'y'), ('PRINTERLIST', 'PRNT3')]:
    conf[name] = value

10 Comments

nevermind, i found the python 3.x port here bitbucket.org/zubin71/configobj-py3.
@mstefan: set raise_errors=True for the ConfigObj() and .write() calls. Set character encoding in the ConfigObj() call explicitly. "doesn't work" is too vague: what is in the 'test.conf' file? What do you get and what do you expect to see (update your question with examples of correct input/output)? What do sys.version and configobj.__version__ contain?
My impression is that mstefan wants to change the value of the variable, and not the variable name. (Although he does not specify what he wants to have changed.)
@J.F. Sebastian: raise_errors helped realize that it is failing because the conf file im editing has a couple lines that have the ' symbol: dateformat = '.' yyyy-MM-dd asciiCode = ',165 so it is giving me a "ParseError: parse error in value at line X"
sorry, formatting gabrled up my message. what i meant to say is that a few lines have the ' symbol which doesnt seem to play nicely with ConfigObj. Any ideas on how to work around those lines?
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.