是否有一个属性可以在读取模式下锁定ConfigParser
对象?
我正在使用项目范围的全局ConfigParser
对象,我想阻止代码修改对象。如果调用该方法,我可以轻松覆盖ConfigParser.set(section,option,value)
以引发错误,但我想知道我是否没有忽略更简单的解决方案。
答案 0 :(得分:0)
我找到了解决这个问题的通用解决方案(使用Felix Kling在这里写的这个奇妙的片段:How to create a constant in Python)。 我的目标是使用一些防御性编程简化调试器的工作,而不是防止任何恶意访问类。
此外,它是一种hackish:常量成员和私有/受保护访问确实与Python的哲学相吻合('明显优于隐式',......)。
首先,我们必须阻止来自ConfigParse的任何setter:轻松,我们只需要覆盖set(self, section, option, value)
:
def set(self, section, option, value):
raise SyntaxError("No modification authorized")
这部分有点问题:为了控制常量成员的setter,我们必须使用@property
装饰器将方法伪装成成员。 @constant
装饰器只是一个修改过的@property
装饰器:
# Constant decorator
def constant(f):
def fset(self, value):
raise SyntaxError("Don't touch that !")
def fget(self):
return f(self)
return property(fget, fset)
# Config Class. Notice the object name in the type of class FixedConfig has to derived from
# ( Python 2.xx and new-style class purpose)
# (see more here : https://stackoverflow.com/questions/598077/why-does-foo-setter-in-python-not-work-for-me )
class FixedConfig( object, ConfigParser):
def __init__(self):
ConfigParser.__init__()
self.read("filepath to config file")
def set(self, section, option, value):
raise SyntaxError("No modification authorized")
#fake DNS service : map domain names to IP
@constant
def DNS(self):
return { self.get("domain names", IP) : IP \
for IP in self.options("domain names") )
最后,你必须防止重写类方法(Python的猴子补丁的神奇之处)。这种修改不常见,但可能发生(特别是在处理依赖性反转时)。在我们的例子中,我们不希望重写FixedConfig.set
:
config = FixedConfig()
print config.get("domain names", "127.0.0.1")
#>> 'localhost'
config.set = super(FixedConfig,self).set # swap FixedConfig.set with ConfigParser.set
config.set("domain names", "127.0.0.1", "CommandAndControl")
print config.get("domain names", "127.0.0.1")
#>> 'CommandAndControl'
要防止它,您只需使用set
修饰@constant
方法。
同样,它不会阻止恶意人员重写常量装饰器并覆盖set属性(我不认为我们可以在Python中使用这种保护)但仍然更容易跟踪调用常量装饰器而不是整个项目中对配置成员的调用。