使用Python编写的配置文件

时间:2014-05-10 23:54:11

标签: python configuration-files

我注意到一些使用Python编写的配置文件的Python包。除了明显的特权升级之外,这种方法的优点和缺点是什么?

这有什么优先权吗?是否有关于实施此方法的最佳方法的指南?

只是为了澄清:在我的特定用例中,这只会被程序员或知道他们正在做什么的人使用。它不是将分发给最终用户的软件中的配置文件。

5 个答案:

答案 0 :(得分:4)

我能想到的最好的例子是django settings.py文件,但我确信还有很多其他的例子可以使用Python文件进行配置。

使用Python作为配置文件比使用其他解决方案有几个关键优势,例如:

  • 无需解析文件:由于该文件已经是Python,因此您无需编写或导入解析器以从文件中提取键值对。
  • 配置设置可能不仅仅是键/值:虽然让设置定义自己的类会很愚蠢,但您可以使用它们来定义设置的元组,列表或词典,从而允许更多选项和配置比其他选项。 django尤其如此,其中设置文件必须适应框架设计者最初不知道的各种插件。
  • 编写配置文件很简单:这很虚假,但由于配置是Python文件,因此可以在程序本身的IDE中编辑和调试。
  • 隐式错误检查:如果您的程序需要一个名为FILE_NAME的选项且该设置不在设置中,程序将抛出异​​常。这意味着设置成为必需设置,并且设置的错误处理可以更明确。这可能是一把双刃剑,但手动更改配置文件应该适用于应该能够处理异常后果的电源编辑器。
  • 可以轻松访问配置选项和命名空间:一旦您import settings,您可以疯狂地开始调用settings.UI_COLORsettings.TIMEOUT。这些都很清楚,使用正确的IDE,跟踪这些设置的位置变得比使用平面文件更容易。

但最有力的原因: 覆盖,覆盖,覆盖 。这是一个非常先进的情况,可以是特定于用例的,但是django在一些地方鼓励这种情况。

说明您正在构建一个Web应用程序,其中有一个开发和生产服务器。其中每个都需要自己的设置,但其中90%是相同的。在这种情况下,您可以执行诸如定义涵盖所有开发的配置文件并使其(如果更安全)作为默认设置,然后覆盖 if 其生成,如下所示:

PORT = 8080
HOSTNAME = "dev.example.com"
COLOR = "0000FF"

if SITE_IS_LIVE:
    import * from production_settings.py

执行import * from将导致production_settings.py文件中声明的任何设置覆盖设置文件中的声明。

我没有看到涵盖如何执行此操作的最佳做​​法指南或PEP文档,但如果您需要一些通用指南,则django settings.py是一个很好的示例。 < / p>

  • 使用一致的变量名称,最好是大写,因为它们被理解为设置或常量。
  • 如果您使用Python作为配置语言,那么期待奇怪的数据结构,然后尝试处理所有基本数据类型。
  • 不要尝试创建一个界面来更改设置,这不是一个简单的文本编辑器。

什么时候不应该使用这种方法?当您处理需要由新手用户更改的简单键/值对时。 Python配置只是的高级用户选项。新手用户将忘记结束引号或列表,不一致,将删除他们认为不适用的选项,并将提交最不合适的不请求,并将混合制表符和空格空格。因为你实际上是处理代码而不是配置文件,所以这些打破你的程序。在另一方面,编写一个可以通过python文件解析以找到合适的选项并更新它们的工具可能比它的价值更麻烦,你最好重用现有的模块,如ConfigParser < / p>

答案 1 :(得分:2)

我认为Python代码直接用于配置主要是因为它是如此简单,快速,强大且灵活的方式来完成它。目前,Python生态系统中没有其他工具可以将所有这些优势结合在一起。 ConfigParserShootout cat给出了足够的理由说明为什么将Python代码作为配置滚动可能更好。

有一些安全注意事项可以通过防御性代码评估或通过策略(例如在部署中正确设置文件系统权限)来解决。

我已经看到了使用各种解析器以各种格式完成相当复杂的配置的困难,但最终在代码中完成最简单。

我遇到的唯一真正的缺点是管理配置的人必须有点意识到Python,至少是语法,能够做任何事情而不是制造任何东西。可能会或可能不会视具体情况而定。

此外,一些严肃的项目,如Django和Sphinx,正在使用这种方法应该足够安慰:

答案 2 :(得分:0)

编写配置文件有很多选项,编写良好的解析器:

没有任何理由将任何类型的配置直接解析为python脚本。这可能会导致许多问题,从安全方面到难以调试的错误,可能会在程序生命周期的后期产生。

甚至discussions为python包构建setup.py的替代方案,这与python编程器的python源代码配置非常接近图。

否则,您可能只是看到python对象导出为字符串,看起来有点像json,虽然更灵活一点......只要你没有eval() / {这就完全没问题{1}}它们甚至可以导入它们,但是将它传递给解析器,如'ast.literal_eval'parsing,这样您就可以确保只加载静态数据而不是可执行代码。

我唯一理解的东西是接近用python编写的配置文件,是一个包含在库中的模块,它定义了该库使用的常量,由库的用户处理。我甚至不确定这是一个好的设计决定,但我理解这样的事情。

编辑:

我不会将django的settings.py视为良好做法的一个例子,尽管我认为这是我认为编码文化用户的配置文件的一部分工作正常,因为django的目标主要是由编码员和系统管理员使用。此外,django还提供了一种通过网页进行配置的方式。

采取@ lego的论据:

  • 无需解析文件

没有必要明确解析它,虽然解析的成本是轶事,甚至更多考虑到安全性和额外的安全性以及早期发现问题的能力

  • 配置设置不仅仅是键/值
除了ini文件之外,您可以使用json / yaml或xml定义几乎任何基本的python类型。而且您不想在配置文件中定义类或实例化复杂对象......

  • 编写配置文件很简单:

但是使用一个好的编辑器,可以检查和验证json / yaml甚至xml语法,以获得一个完美的可解析文件。

  • 隐式错误检查:

也不是一个参数,正如你所说的那样,你可以得到一些解析得很好的东西,但是经过几个小时的运行会导致异常。

  • 可以轻松访问配置选项和命名空间:

使用json / yaml或xml,选项可以很容易地命名空间,并自然地用作python对象。

  • 但最强大的原因:覆盖,覆盖,覆盖

这不是一个好的论据,也不支持python代码。考虑到你的代码是由几个相互关联的模块组成并使用一个通用配置文件,并且每个模块都有自己的配置,那么首先将主配置文件作为一个好的旧python字典加载是非常容易的,刚刚通过更新字典加载的其他配置文件。

如果您想跟踪更改,那么有许多配方可以组织一个dicts层次结构,如果它不包含值,则会回退到另一个dict。

最后,在运行时更改的配置值无法(实际上不应该)在python中正确序列化,因为这样做意味着更改当前正在运行的程序。

我并不是说你不应该使用python存储配置变量,我只是说你选择的语法不一样,你应该通过解析器获取它,然后再将它作为实例存储在你的实例中程序。永远不要加载用户可修改的内容而不进行双重检查。永远不要相信您的用户!

如果django人员正在这样做,那是因为他们已经构建了一个框架,只有在将许多插件聚集在一起构建应用程序时才有意义。然后,要配置应用程序,您将使用数据库(这是一种配置文件...类固醇)或实际文件。

HTH

答案 3 :(得分:0)

我在公司内部工具和游戏中经常这样做。简单的主要原因是:您只需导入文件,而无需关心格式或解析器。通常它正是@zmo所说的,常量意味着团队中的非程序员要修改(比如游戏关卡的网格大小或显示分辨率)。

有时能够在配置中使用逻辑非常有用。例如,填充游戏中的板的初始配置的替代功能。我发现这实际上是一个很大的优势。

我承认这可能导致难以调试问题。也许在这些情况下,这些模块更像是游戏级init模块,而不是典型的配置文件。无论如何,我一直非常高兴能够直接制作明确的文本配置文件,并且能够在那里拥有逻辑并且没有得到它。

答案 4 :(得分:0)

这是另一个配置文件选项。有几种非常适合的配置文件格式。

请花点时间了解系统管理员的观点或支持您产品的第三方供应商。如果还有其他配置文件格式,他们可能会放弃您的产品。如果你的产品具有巨大的重要性,那么人们将只是为了阅读你的配置文件而学习语法的麻烦。 (比如X.org或apache)

如果您计划使用另一种编程语言来访问/编写配置文件信息,那么基于python的配置文件将是一个坏主意。