python RawConfigParser

时间:2015-01-29 15:24:26

标签: python class configuration-files configparser

我正在使用RawConfigParser来读取和更新ini样式配置文件。这在标准配置中没有任何问题。 我的问题是我在同一个脚本中读取不同的配置文件。没有太多细节,当我读取第二个配置文件时,它的值与第一个ini文件合并。

两个ini文件的原始内容

infile_1.ini
[section]
option = Original value
extraoption = not in ini file 2

inifile_2.ini
[section]
option = Original value

这是我用来改变ini文件内容的代码。这是重现问题的一小段代码

import ConfigParser

class status_file:
   myConfig = ConfigParser.RawConfigParser()
   myConfig.optionxform = str

   def __init__(self, str_statusfile):
      self.myConfig.read( str_statusfile)
      self.statusfile = str_statusfile

   def option(self, new_value):
      self.myConfig.set("section","option",new_value)
      with open( self.statusfile, "w") as ini_out:
            self.myConfig.write( ini_out )


statusfiles = ['inifile_1.ini', 'inifile_2.ini']
for myStatus in statusfiles:
   myConfig = status_file(myStatus)
   myConfig.option("Something new")

执行此代码后,ini文件的内容已根据需要进行了更改。但是在第二个ini文件中,第一个ini文件中的选项被合并。

infile_1.ini
[section]
option = Something New
extraoption = not in ini file 2

inifile_2.ini
[section]
option = Something New
extraoption = not in ini file 2

我是否可以通过某种方式重置ConfigParser内容或其他解决方案? 我想这与构造和解构ConfigParser对象有关? 我没有上课就尝试了,然后没有问题。 我是Python的初学者,所以这可能不是处理这个问题的最好方法。 实际应用程序是动态的,因为在使用应用程序期间ini文件的数量和位置会发生变化。 ini文件列表使用os.listdir(folder)

构建

2 个答案:

答案 0 :(得分:1)

您正在制造的混乱是如下定义ConfigParser:

class status_file:
   myConfig = ConfigParser.RawConfigParser()
   myConfig.optionxform = str

   def __init__(self, str_statusfile):
       ...

使myConfig属性成为status_file属性,与Java不同。 因此,当您解析第二个文件时,相同的配置将解析它,并将其选项与它解析的第一个文件合并。

要避免您的问题,只需在__init__方法内创建解析器作为实例属性:

class status_file(object):

   def __init__(self, str_statusfile):
       self.myConfig = ConfigParser.RawConfigParser()
       self.myConfig.optionxform = str
       ...

作为旁注,如果您使用的是Python 2.x版,则您的类应该继承自object。否则你将拥有旧式(pre-python2.2)类,这些类可能会给你带来很多微妙的问题。

答案 1 :(得分:1)

对于初学者来说,这是常见的python错误。我假设你懂得像Java或C ++这样的语言,不是吗?

在您的班级myConfig中是班级的属性,而不是它的实例。默认Python行为首先在实例属性中查找,然后在类属性中查找,因此self.myConfig在两个实例中都是完全相同的解析器。有关详细信息,请参阅this

您的解决方案是在构造函数(__init__)中创建和配置解析器,而不是类声明。

这可以帮助您理解为什么myConfig是class属性,而不是实例属性: 当你写这样的东西时:

class A(B, C):
    def foo(x):
        return 2*x

它只是语法糖:

def foo(x):
    return 2*x
A = type("A", (B, C), {"foo": foo})
del foo

如果您需要动态创建新类,这可能会派上用场。 由于A是类,它的__call__方法最终导致调用它的__new____init__方法,这将导致创建新实例,它将与它的A属性共享相同的对象__class__(这是简化,它不是所有内部发生的,但对于一般的Python来说它足够了; ))。