【发布时间】:2015-11-24 13:08:37
【问题描述】:
我想以一种高效的方式为项目创建配置文件 方便编码器的开发和用户的定制。
我有一个名为projectConf 的配置模块,它包含不同的类,每个类都有配置属性:
class Config1:
C_1_1 = "string"
C_1_2 = ["string1", "string2"]
C_1_3 = 4
class Config2:
C_2_1 = "another string"
C_2_2 = 10
我确实可以将属性放入很好的字典中,但我使用类来保存我的数据以方便开发。事实上,使用任何体面的 IDE,我都可以导入所需的类并利用自动完成功能直接查看哪些字段可用。 我目前使用 Pycharm。我对此很满意,而且我不知道任何 IDE 自动完成 dict 键。但这是偏好问题,最好针对最常见的 IDE 并找到通用解决方案。
我的属性保持默认配置。但是这些必须在文本配置文件中呈现给任何用户可用。所以我的下一步是获取所有类的属性。
在同一个模块projectConf我实现了以下方法来打印每个类的属性:
import sys, inspect
def printClassFields():
for name, obj in inspect.getmembers(sys.modules[__name__], inspect.isclass):
print "\nName: ", name, "\tObj: ", obj
for field in getClassVariables(name):
value = getClassField(name, field)
msg = field + " = " + ", ".join(value) if isinstance(value, list) else field + " = " + str(getClassField(name, field))
print " " + msg
所以我使用sys.module[__name__]。我可以使用这种方法来编写一个基本的配置文件。理想情况下,最好有一个从配置文件中分离出来的模块,它将编写任何文件配置模块,例如projectConf。所以我写了模块configWriter,其中包含ClassAttributesReader类:
import sys, inspect
class ClassAttributesReader:
def __init__(self, moduleName):
self._moduleName = moduleName
if moduleName:
print "[Reading module] ", moduleName
def printClassFields(self):
for name, obj in inspect.getmembers(self._moduleName, inspect.isclass):
print "\nName: ", name, "\tObj: ", obj
for field in self.getClassVariables(name):
value = self.getClassField(name, field)
msg = field + " = " + ", ".join(value) if isinstance(value, list) else field + " = "\
+ str(self.getClassField(name, field))
print " " + msg
def getClassField(self, className, variableName):
"""
Retrieves the value of a class variable.
:param className:
:param variableName:
:return:
"""
try:
return eval(str(className) + "." + str(variableName))
# print className + "." + variableName + " = " + eval(str(className) + "." + str(variableName))
except NameError as ne:
print "ERROR: " + ne.message
def evalContent(self, content):
eval(content)
我通过这种方式从projectConf 调用ClassAttributesReader:
import sys
class Config1:
C_1_1 = "string"
C_1_2 = ["string1", "string2"]
C_1_3 = 4
class Config2:
C_2_1 = "another string"
C_2_2 = 10
def main(argv=None):
from configWriter import ClassAttributesReader
car = ClassAttributesReader(sys.modules[__name__])
car.printClassFields()
if __name__ == "__main__":
sys.exit(main(sys.argv))
这里的问题是ClassAttributesReader这个类需要导入projectConf等配置文件模块。我不知道如何正确执行此操作,我尝试在ClassAttributeReader 中使用eval 来动态进行导入:
def evalContent(self, content):
eval(content)
唉,没有成功。我不知道该怎么做。所以此时我正在考虑将配置模块中的所有类属性转换为字典,然后将其传递给ClassAttributeReader。这种方式可以规避导入问题,也许
它可能不太容易出错?但是这种转换方法需要与printClassFields 和sys.module[__name__] 方法相同类型的代码。如果我想将此方法放在ClassAttributeReader 中,我仍然需要处理动态导入。
所以我想知道是否有更好的方法来解决这个问题,是否将配置属性放在类变量中以用于自动完成目的。最终,如果我的解决方案看起来不错,我需要一种方法来进行动态导入。
你怎么看?
编辑 1
只是为了提请您注意,我知道 argparse 模块,并且我打算使用它来从配置文件中读取属性。我的问题是不同的。我想要一种从我的配置类中的硬编码属性为用户生成该配置文件的方法,如上所示。因此用户可以在这个新生成的配置文件中看到默认的硬编码属性,然后在需要时更改这些属性。然后,我的程序将在运行时根据用户的更新这些值。
【问题讨论】:
标签: python import configuration