【问题标题】:Organizing configuration file and variables组织配置文件和变量
【发布时间】: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


    【解决方案1】:

    我知道你要这么做了,但你应该停下来。问题是,您永远不想“执行”配置文件,因为那里可能会出现很多随机的东西并给您带来问题。最好使用 INI 或 JSON 文件。将文件加载到 dicts 中并直接使用 dicts 或使用 dicts 中的值填充配置对象。

    查看配置解析器:https://docs.python.org/2/library/configparser.html

    【讨论】:

    • 您的意思是可以保留我的类和属性,并且应该使用 .ini 文件对其进行初始化?或者也摆脱那些类属性?
    • 是的,您可以使用对象来存储您的配置,只需使用这些库之一将 json 或 ini 文件读入 dict。您甚至可以使用这样的方法来加载文件: class MyConfigurationClass(object): def __init__(config_file = None): if config_file: config_dict = load_ini_config_file(config_file) self.setting1 = config_dict.get("setting1", setting1_default)
    • 谢谢,我关心的不是读取配置文件,而是从我的类中的默认硬编码属性生成它。然后一旦生成,我当然会在运行时解析它以更新硬编码的属性。
    • 是的,在这种情况下,您只需构建所有配置变量的字典,并使用库将其转储为 JSON 或 INI。
    猜你喜欢
    • 2012-02-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-24
    • 1970-01-01
    • 2015-03-27
    • 2020-02-03
    • 1970-01-01
    相关资源
    最近更新 更多