在 Python 中设置配置文件的最佳方法是啥

Posted

技术标签:

【中文标题】在 Python 中设置配置文件的最佳方法是啥【英文标题】:What is the best method for setting up a config file in Python在 Python 中设置配置文件的最佳方法是什么 【发布时间】:2018-09-13 14:09:12 【问题描述】:

我意识到这个问题之前曾被问过 (What's the best practice using a settings file in Python?),但鉴于 7 年前有人问过这个问题,我觉得有必要再次讨论一下技术是如何发展的。

我有一个 python 项目,它需要根据环境变量的值使用不同的配置。由于使用环境变量选择配置文件很简单,所以我的问题如下:

当需要根据环境进行多种配置时,什么格式被视为软件行业中在 python 中设置配置文件的最佳实践?

我意识到 python 带有一个 ConfigParser 模块,但我想知道使用 YAML 或 JSON 等格式是否会更好,因为它们易于跨语言使用而越来越受欢迎。当您有多种配置时,哪种格式更容易维护?

【问题讨论】:

您提到的问题在几个月前被关闭,因为它过于宽泛。您的版本似乎更广泛。 此外,似乎在该问题关闭前几个小时对该问题进行了全面清理——所有过时的答案都已删除,并编辑了其他答案之一以提供有关 YAML 的更新信息 (并且此后再次更新)。 同时,JSON 的相对“流行度”确实无关紧要。问题是您的实际用户对您的实际应用程序最熟悉或最有用的是什么。 INI/rc 格式、可执行 Python 代码、JSON 等都有明显的优点和缺点。如果有一个答案是所有可能用途的最佳答案,那么我们今天不会有比我们更多的竞争方式来做到这一点十年前,我们都会使用一个。 (尽管至少我们不再经常使用“具有隐式但未定义模式的非常复杂的 XML 语言”……) 公平地说,我会调整我的问题以尝试降低价值。诚然,它们是每种格式的优势,但软件行业内肯定必须对所谓的“最佳实践”达成某种共识。归根结底,这是一个非常微不足道的设计决定,必须做出,但我想找到行业内的共同共识或某些工作空间内的基本原则。 嗯,“至少在某些工作区”正是问题所在。不同的工作空间有不同的答案。部分是由他们使用的技术驱动的(Django 商店更有可能拥有可执行的配置,混合大量 Python 和 Ruby 以拥有 YAML 的多语言商店等),但它也受到他们应用程序的特定需求的驱动/用户。而且这些考虑都没有一个适用于整个“行业”的普遍答案。这就是为什么仍然有这么多“行业标准”的原因。 【参考方案1】:

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

它并不太喜欢 JSON 或 YAML 配置文件 - 它只是使用一个名为 settings.py 的 python 模块,可以将它导入到需要访问设置的任何其他模块中。那里还定义了基于环境变量的设置。这是 Github 上 Django 的示例 settings.py 文件的链接:

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

【讨论】:

【参考方案2】:

如果你真的想使用基于环境的 YAML 配置,你可以这样做:

config.py

​​>
import yaml
import os

config = None

filename = 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】:

这实际上取决于您的要求,而不是格式的受欢迎程度。例如,如果您只需要简单的键值对,那么 INI 文件就足够了。只要您需要复杂的结构(例如数组或字典),我就会选择 JSON 或 YAML。 JSON 只是存储数据(它更适用于系统之间的自动化数据流),而 YAML 更适合人工生成(或维护或读取)文件,因为它具有 cmets,您可以在文件中的其他位置引用值......并且最重要的是,如果您想要健壮性、灵活性以及检查文件正确结构的方法(但不太关心数据的手动编辑),我会选择 XML。

【讨论】:

【参考方案4】:

我建议给trapdoor 尝试一下交钥匙配置(免责声明:我是陷门的作者)。

【讨论】:

【参考方案5】:

这真的很晚了,但这是我使用的,我很满意(如果你愿意接受纯 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

【讨论】:

【参考方案6】:

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

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

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

【讨论】:

以上是关于在 Python 中设置配置文件的最佳方法是啥的主要内容,如果未能解决你的问题,请参考以下文章

在 tomcat webapp 中设置身份验证的最佳方法是啥?

以编程方式在 iOS 设置中设置全局 Http 代理的可能方法是啥?

Gitlab CI/CD 中设置 Python 虚拟环境的最佳实践是啥

在 Zend Framework 2 中设置视图插件的最佳方法是啥?

在 Kubernetes 的 Nginx Ingress 对象中设置代理通道的最佳方法是啥

在小部件中设置 Firebase 崩溃用户标识符的最佳方法是啥?