質問

Simple question. It is possible to make configobj to not put a space before and after the '=' in a configuration entry ?

I'm using configobj to read and write a file that is later processed by a bash script, so putting an antry like:

VARIABLE = "value"

breaks the bash script, it needs to always be:

VARIABLE="value"

Or if someone has another suggestion about how to read and write a file with this kind of entries (and restrictions) is fine too.

Thanks

役に立ちましたか?

解決 3

Well, as suggested, I ended up writing my own parser for this that can be used exactly in the same way as ConfigObj:

config = MyConfigParser("configuration_file")
print config["CONFIG_OPTION_1"]  
config["CONFIG_OPTION_1"]= "Value 1"
print config["CONFIG_OPTION_1
config.write()

This is the code if someone is interested or wants to give suggestions (I started coding in python not so long ago so probably there are lots of room for improvement). It respects the comments and the order of the options in the file, and correctly scapes and adds double quotes where needed:

import os
import sys

class MyConfigParser:
  name = 'MyConfigParser'
  debug = False
  fileName = None
  fileContents = None
  configOptions = dict()  

  def __init__(self, fileName, debug=False):
    self.fileName = fileName
    self.debug = debug    
    self._open()

  def _open(self):       
    try:
        with open(self.fileName, 'r') as file:
    for line in file:
      #If it isn't a comment get the variable and value and put it on a dict
      if not line.startswith("#") and len(line) > 1:
    (key, val) = line.rstrip('\n').split('=')
    val = val.strip()
    val = val.strip('\"')
    val = val.strip('\'')
    self.configOptions[key.strip()] = val
except:
  print "ERROR: File "  + self.fileName + " Not Found\n"

  def write(self):
try:
  #Write the file contents
  with open(self.fileName, 'r+') as file:
    lines = file.readlines()
    #Truncate file so we don't need to close it and open it again 
    #for writing
    file.seek(0)
    file.truncate()      

    i = 0
    #Loop through the file to change with new values in dict      
    for line in lines:    
      if not line.startswith("#") and len(line) > 1:
    (key, val) = line.rstrip('\n').split('=')
    try:
      if key in line:
        newVal = self.configOptions[key]
        #Only update if the variable value has changed
        if val != newVal:
          newLine = key + "=\"" + newVal + "\"\n"
          line = newLine
    except:
      continue
      i +=1
      file.write(line)
except IOError as e:
  print "ERROR opening file " + self.fileName + ": " + e.strerror + "\n"


  #Redefinition of __getitem__ and __setitem__

  def __getitem__(self, key):  
try:
  return self.configOptions.__getitem__(key)
except KeyError as e:
  if isinstance(key,int):
    keys = self.configOptions.keys()
    return self.configOptions[keys[key]]
  else:
    raise KeyError("Key " +key+ " doesn't exist")

  def __setitem__(self,key,value):
self.configOptions[key] = value

他のヒント

I was looking into same and modified configobj.py by changing line 1980 in:

def _write_line(self, indent_string, entry, this_entry, comment)

from:

self._a_to_u(' = ')

to:

self._a_to_u('=')

After the change the output is without the space before and after equal sign.

Configobj is for reading and writing ini-style config files. You are apparently trying to use it to write bash scripts. That's not something that is likely to work.

Just write the bash-script like you want it to be, perhaps using a template or something instead.

To make ConfigParses not write the spaces around the = probably requires that you subclass it. I would guess that you have to modify the write method, but only reading the code can help there. :-)

As suggested above, it is possible to remove the spaces either side of the equals sign by making a small change to the _write_line method. This can be done conveniently by subclassing ConfigObj and overwriting _write_line as follows -

from configobj import ConfigObj

class MyConfigObj(ConfigObj):

    def __init__(self, *args, **kwargs):
        ConfigObj.__init__(self, *args, **kwargs)

    def _write_line(self, indent_string, entry, this_entry, comment):
        """Write an individual line, for the write method"""
            # NOTE: the calls to self._quote here handles non-StringType values.
        if not self.unrepr:
            val = self._decode_element(self._quote(this_entry))
        else:
            val = repr(this_entry)

        return '%s%s%s%s%s' % (indent_string,
                           self._decode_element(self._quote(entry, multiline=False)),
                           self._a_to_u('='),
                           val,
                           self._decode_element(comment))

Then just use MyConfigObj in place of ConfigObj and all the functionality of ConfigObj is maintained

As Lennart suggests, configobj is probably not the right tool for the job: how about:

>>> import pipes
>>> def dict2bash(d):
...     for k, v in d.iteritems():
...         print "%s=%s" % (k, pipes.quote(v))
...         
>>> dict2bash({'foo': "bar baz quux"})
foo='bar baz quux'

since configobj returns something that looks a lot like a dict, you could probably still use it to read the data you are trying to process.

First of all, thanks Juancho. That's what i was looking for. But i edited the ConfigParser a little bit. Now it can handle bash script arrays in form of:

# Network interfaces to be configured
ifaces=( "eth0" "eth1" "eth2" "eth3" )

If you set a value it just proves if an value is a list and if, it sets the quotes correctly. So you can set values still the same way, even it is a list:

ifaces = ['eth0', 'eth1', 'eth2', 'eth3']
conf['ifaces'] = ifaces

Here's the code:

import os
import sys

class MyConfigParser:
    name = 'MyConfigParser'
    debug = False
    fileName = None
    fileContents = None
    configOptions = dict()  
    qouteOptions = dict()

    def __init__(self, fileName, debug=False):
        self.fileName = fileName
        self.debug = debug    
        self._open()

    def _open(self):       
        try:
            with open(self.fileName, 'r') as file:
                for line in file:
                    #If it isn't a comment get the variable and value and put it on a dict
                    if not line.startswith("#") and len(line) > 1:
                        (key, val) = line.rstrip('\n').split('=')
                        val = val.strip()
                        val = val.strip('\"')
                        val = val.strip('\'')
                        self.configOptions[key.strip()] = val
                        if val.startswith("("):
                            self.qouteOptions[key.strip()] = ''
                        else:
                            self.qouteOptions[key.strip()] = '\"'
        except:
            print "ERROR: File "  + self.fileName + " Not Found\n"

    def write(self):
        try:
            #Write the file contents
            with open(self.fileName, 'r+') as file:
                lines = file.readlines()
                #Truncate file so we don't need to close it and open it again 
                #for writing
                file.seek(0)
                file.truncate()      

                #Loop through the file to change with new values in dict      
                for line in lines:
                    if not line.startswith("#") and len(line) > 1:
                        (key, val) = line.rstrip('\n').split('=')
                        try:
                            if key in line:
                                quotes = self.qouteOptions[key]

                                newVal = quotes +  self.configOptions[key] + quotes

                                #Only update if the variable value has changed
                                if val != newVal:
                                    newLine = key + "=" + newVal + "\n"
                                    line = newLine
                        except:
                            continue
                    file.write(line)
        except IOError as e:
                print "ERROR opening file " + self.fileName + ": " + e.strerror + "\n"


    #Redefinition of __getitem__ and __setitem__

    def __getitem__(self, key):  
        try:
            return self.configOptions.__getitem__(key)
        except KeyError as e:
            if isinstance(key,int):
                keys = self.configOptions.keys()
                return self.configOptions[keys[key]]
            else:
                raise KeyError("Key " + key + " doesn't exist")

    def __setitem__(self, key, value):
        if isinstance(value, list):
            self.qouteOptions[key] = ''
            value_list = '('
            for item in value:
                value_list += ' \"' + item + '\"'
            value_list += ' )'
            self.configOptions[key] = value_list
        else:
            self.qouteOptions[key] = '\"'
            self.configOptions[key] = value
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top