Python中设置配置文件的最佳方法是什么?

9
我意识到这个问题之前已经被问过(Python中使用设置文件的最佳实践是什么?),但考虑到这是7年前提出的,我觉得再次讨论是有意义的,因为技术已经发展了。

我有一个需要根据环境变量的值使用不同配置的Python项目。由于使用环境变量选择配置文件已经足够简单,所以我的问题是:

在Python中,当需要基于环境使用多个配置时,哪种格式被视为软件行业最佳实践来设置配置文件?

我知道Python带有ConfigParser模块,但我想知道是否最好使用像YAML或JSON这样的格式,因为它们由于易于跨语言使用而变得越来越流行。当你有多个配置需要维护时,哪种格式更容易维护?


你所提到的问题几个月前因为过于宽泛而被关闭。你的版本似乎更加宽泛。 - abarnert
此外,似乎在那个问题关闭之前几个小时进行了一次普遍的清理--所有过时的答案都被删除了,另一个回答被编辑以提供关于YAML的更新信息(并已再次更新)。 - abarnert
与此同时,JSON的“流行程度”并不重要。问题是什么对于您实际应用程序的实际用户最熟悉或可用。INI / rc格式,可执行Python代码,JSON等都有明显的优缺点。如果有一个答案适用于所有可能的用途,那么今天我们就不会比十年前拥有更多竞争方式来做到这一点,我们都将使用其中之一。(尽管至少我们现在很少有“具有隐含但未定义模式的真正复杂的XML语言”……) - abarnert
好的,我会调整我的问题,尽量减少价值判断。没错,每种格式都有其优点,但在软件行业中肯定有一些共识被视为“最佳实践”。归根结底,这是一个非常琐碎的设计决策,但我想找到行业内或至少某些工作空间内的共识。 - Keegan Ferrett
嗯,"至少在某些工作区"这正是问题所在。不同的工作区有不同的答案。部分原因是由于它们使用的技术(Django商店更可能拥有可执行配置,混合大量Python和Ruby的多语言商店则更可能使用YAML等),但也受到其应用程序/用户特定需求的驱动。而这两个考虑因素都没有普遍适用于整个行业的通用答案。这正是为什么仍然有这么多关于此的“行业标准”的原因。 - abarnert
6个回答

3
如果您真的想使用基于环境的YAML配置,可以像这样操作:

config.py

import yaml
import os

config = None

filename = os.getenv('env', 'default').lower()
script_dir = os.path.dirname(__file__)
abs_file_path = os.path.join(script_dir, filename)
with open(abs_file_path, 'r') as stream:
    try:
        config = yaml.load(stream)
    except yaml.YAMLError as exc:
        print(exc)

3
这个问题有些晚了,但这是我使用的方法,如果你可以接受纯Python解决方案,那么它能够带给你满意的效果。我喜欢它,因为我的配置可以根据部署环境自动设置使用环境变量。我还没有长时间使用过,如果有人发现问题,请告诉我。
结构:
|--settings
   |--__init__.py
   |--config.py

config.py

class Common(object):
    XYZ_API_KEY = 'AJSKDF234328942FJKDJ32'
    XYZ_API_SECRET = 'KDJFKJ234df234fFW3424@#ewrFEWF'

class Local(Common):
    DB_URI = 'local/db/uri'
    DEBUG = True

class Production(Common):
    DB_URI = 'remote/db/uri'
    DEBUG = False

class Staging(Production):
    DEBUG = True

__init__.py

from settings.config import Local, Production, Staging
import os

config_space = os.getenv('CONFIG_SPACE', None)
if config_space:
    if config_space == 'LOCAL':
        auto_config = Local
    elif config_space == 'STAGING':
        auto_config = Staging
    elif config_space == 'PRODUCTION':
        auto_config = Production
    else:
        auto_config = None
        raise EnvironmentError(f'CONFIG_SPACE is unexpected value: {config_space}')
else:
    raise EnvironmentError('CONFIG_SPACE environment variable is not set!')

如果我的环境变量在应用程序存在的每个地方都设置了,那么我可以根据需要将其带入我的模块中:
from settings import auto_config as cfg

1
好的做法。只是一个小细节,EnvironmentError自Python 3.3起已被弃用。在这里可能更适合使用ValueError - user22472937
或者考虑使用enum来代替手动引发错误来表示config_space的值。 - user22472937
如果使用API_KEY和API_SECRET进行版本控制,config.py将成为安全风险。这些应该存储在环境变量中。 - undefined

2

我认为查看Python Django设置模块的标准配置是一个很好的例子,因为Python Django Web框架非常受商业项目欢迎,因此代表着软件行业。

它不会使用太过高级的JSON或YAML配置文件 - 它只是使用一个名为settings.py的Python模块,可以导入到需要访问该设置的任何其他模块中。同时也在其中定义了基于环境变量的设置。以下是Django在Github上的示例settings.py文件链接:

https://github.com/deis/example-python-django/blob/master/helloworld/settings.py


1
这实际上取决于您的需求,而不是格式的流行程度。例如,如果您只需要简单的键值对,INI文件就足够了。一旦您需要复杂的结构(例如数组或字典),我会选择JSON或YAML。JSON仅存储数据(它更适用于系统之间的自动化数据流),而YAML更适用于人为生成(或维护、阅读)文件,因为它具有注释,可以在文件中引用其他值...除此之外,如果您想要健壮性、灵活性和检查文件正确结构的手段(但不太关心数据的手动编辑),我会选择XML。

1
我建议尝试使用 trapdoor 进行一键配置(免责声明:我是 trapdoor 的作者)。

0

我也喜欢利用Python源代码无需编译,可以使用纯Python文件进行配置的优势。但在现实世界中,您可能有多个环境,每个环境都需要不同的配置,并且您可能还想从环境变量或未在源代码控制中的文件中读取一些(主要是敏感)信息(以防止错误提交这些信息)。

这就是我写这个库的原因:https://github.com/davidohana/kofiko,它允许您使用纯Python文件进行配置,但也能够从.ini或env-vars覆盖这些配置设置,并支持不同环境的自定义。

关于此的博客文章:https://medium.com/swlh/code-first-configuration-approach-for-python-f975469433b9


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接