从环境变量中读取配置。
项目描述
您想要遵循12factor原则,并从环境中读取您的配置。
您还在各种环境中(开发、预发布、生产等)部署您的项目,并希望能够在某些环境中(尤其是开发环境)设置合理的默认值,这样您就不必携带庞大的非版本控制环境的<.env>文件。但您不希望内置的开发默认值默默地被用于生产。
Fern支持您。
在最简单的情况下,一个<.fern.Env>实例让您可以调用它来从环境变量中读取字符串
>>> env = fern.Env() >>> env('FOO') 'bar'
如果我们尝试这样做,而<.FOO>环境变量未设置,我们将得到一个<.ValueError>。如果这是一个关键配置值,应该始终显式地在环境中设置,那么这可能没关系。如果它不太关键,我们可以设置一个默认值
>>> env = fern.Env() >>> env('DOES_NOT_EXIST', default='hey') 'hey'
我们还可以提供一个环境变量名称的列表, fern将检查每个变量,并给出第一个已设置的值
>>> env = fern.Env() >>> env(['DOES_NOT_EXIST', 'DOES_EXIST']) 'value_of_DOES_EXIST'
所有环境值都是字符串。如果我们想将这个字符串解析成更结构化的数据类型呢?我们可以传递任何一元转换函数来应用于值;例如,int类型本身就是一个一元转换函数:传递一个字符串,它将返回解析为整数的该字符串
>>> env = fern.Env() >>> env('SOME_INT', coerce=int) 6
您可以编写任何喜欢的函数,该函数接受一个字符串并返回任何内容,然后将它传递给 coerce。例如,fern.parse_dj_database_url 可以解析数据库URL,如 'postgres://localhost/dname',并返回Django风格的数据库连接信息字典。
Env 类为 coerce 的某些常见值提供了一些方便的方法。
>>> env = fern.Env() >>> env.integer('SOME_INT') 6 >>> env.boolean('SOME_BOOL') True >>> env.comma_list('SOME_LIST') ['a', 'b', 'c']
integer 方法只是将 int 设置为强制转换函数。
boolean 方法将 fern.parse_boolean 设置为强制转换函数;它将空字符串、'0'、'no'、'f'、'n' 和 'false' 视为 False;其他任何内容都是 True。
comma_list 方法将 fern.parse_comma_list 设置为强制转换函数;它按逗号分割环境值,并将结果值作为列表返回。
现在让我们让事情变得更复杂一些。假设我们想要两种部署模式,dev 和 prod,并且我们有一个配置值 SECRET_KEY。在 dev 模式下,我们希望这个值默认为 "dev secret"(但仍然可以通过 SECRET_KEY 环境变量进行覆盖)。在 prod 模式下,如果 SECRET_KEY 环境变量没有明确设置,我们将引发错误;任何硬编码的默认值在生产使用中都不安全。我们可以通过以下方式实现这一点:
>>> env = fern.Env('MODE', valid_modes=['dev', 'prod']) >>> env('SECRET_KEY', mode_defaults={'dev': "dev secret"})
让我们稍作解释。
在第一行,我们告诉 Fern 我们的有效模式是 dev 或 prod,并且一个名为 MODE 的环境变量将告诉我们我们处于哪种模式。(默认模式是列出的第一个,所以如果 MODE 没有设置,我们将处于 dev 模式。如果 MODE 设置为 valid_modes 中未列出的任何内容,我们将得到一个 ValueError)。
在第二行,我们为 mode_defaults 参数提供了一个字典。这个字典的键是模式名称,值是该模式的默认值。在这种情况下,我们只为 dev 模式提供了一个默认值;在 prod 模式下,如果 SECRET_KEY 环境变量没有设置,你会得到一个 ValueError。因此,对于我们的生产部署,我们只需确保设置 MODE=prod,这将确保服务器不会启动,除非我们还提供了所需的其余配置。在 dev 模式下,我们根本不需要任何环境变量。
更改
0.2 (2017.01.08)
使用便利的强制转换方法修复 mode_defaults。
0.1 (2017.01.07)
初始版本。