是否有将ConfigParser
对象锁定为只读模式的属性?
我正在使用项目范围的全局ConfigParser
对象,并且我想防止代码修改该对象。如果调用该方法,我可以轻松地重写ConfigParser.set(section,option,value)
以引发错误,但我想知道我是否没有忽略一个更简单的解决方案。
是否有将ConfigParser
对象锁定为只读模式的属性?
我正在使用项目范围的全局ConfigParser
对象,并且我想防止代码修改该对象。如果调用该方法,我可以轻松地重写ConfigParser.set(section,option,value)
以引发错误,但我想知道我是否没有忽略一个更简单的解决方案。
我找到了解决这个问题的通用解决方案(使用 Felix Kling 在这里编写的精彩片段:如何在 Python 中创建常量)。我的目标是使用一些防御性编程来简化调试器的工作,而不是防止对类的任何恶意访问。
此外,这有点骇人听闻:常量成员和私有/受保护的访问确实与 Python 的哲学相得益彰(“显式优于隐式”,...)。
首先,我们必须阻止来自 ConfigParse 的任何设置器:简单易行,我们只需要覆盖set(self, section, option, value)
:
def set(self, section, option, value):
raise SyntaxError("No modification authorized")
这部分有点问题:为了控制常量成员上的设置器,我们必须使用@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 中拥有这种保护)但仍然更容易跟踪对常量装饰器的调用而不是而不是在整个项目中调用配置成员。