我正在使用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)
答案 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来说它足够了; ))。