组织配置文件和变量

时间:2015-11-24 13:08:38

标签: python import configuration

我想以有效的方式为项目创建配置文件 促进编码器的开发和用户的定制。

我有一个名为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)

我以ClassAttributesReader的方式致电projectConf

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。我不知道如何正确地执行此操作,我尝试使用eval中的ClassAttributeReader动态进行导入:

 def evalContent(self, content):
        eval(content)
唉,没有成功。我不知道该怎么做。所以在这一点上,我正在考虑从配置模块转换所有类属性并将它们转换为字典,这将被传递给ClassAttributeReader。这种方式会绕过进口问题,也许 它可能不那么容易出错?但是这种转换方法需要与printClassFields方法sys.module[__name__]相同的代码。如果我想将此方法放在ClassAttributeReader中,我仍然需要处理动态导入。

所以我想知道是否有更好的方法来解决这个问题,是将配置属性放在类变量中以实现自动完成目的。最终,如果我的解决方案看起来不那么糟糕,我需要一种方法来进行动态导入。

你接受了什么?

编辑1

只是为了引起你的注意,我知道argparse模块,我打算用它来从配置文件中读取属性。我的问题不同。我想要一种方法从我的配置类中的硬编码属性为用户生成该配置文件,如上所示。因此,用户可以在此新生成的配置文件中查看默认的硬编码属性,然后根据需要更改这些属性。然后,我的程序将根据用户在运行时更新这些值。

1 个答案:

答案 0 :(得分:0)

我知道你要去哪里,但你应该停下来。问题是,你不希望永远“执行”配置文件,因为很多随机的事情可能会在那里结束并导致你的问题。最好使用INI或JSON文件。将文件加载到dicts中并直接使用dicts或使用dicts中的值填充配置对象。

请参阅configparser:https://docs.python.org/2/library/configparser.html