简化环境变量解析
项目描述
environs:简化环境变量解析
environs 是一个Python库,用于解析环境变量。它允许您将配置与代码分开存储,遵循 《十二要素应用》 方法。
内容
- 特性
- 安装
- 基本用法
- 支持类型
- 读取
.env
文件 - 处理前缀
- 变量扩展
- 验证
- 延迟验证
- URL方案
- 序列化
- 定义自定义解析器行为
- 与Flask一起使用
- 与Django一起使用
- 为什么...?
- 许可证
特性
安装
pip install environs
基本用法
设置一些环境变量...
export GITHUB_USER=sloria
export MAX_CONNECTIONS=100
export SHIP_DATE='1984-06-25'
export TTL=42
export ENABLE_LOGIN=true
export GITHUB_REPOS=webargs,konch,ped
export GITHUB_REPO_PRIORITY="webargs=2,konch=3"
export COORDINATES=23.3,50.0
export LOG_LEVEL=DEBUG
使用environs解析它们...
from environs import Env
env = Env()
env.read_env() # read .env file, if it exists
# required variables
gh_user = env("GITHUB_USER") # => 'sloria'
secret = env("SECRET") # => raises error if not set
# casting
max_connections = env.int("MAX_CONNECTIONS") # => 100
ship_date = env.date("SHIP_DATE") # => datetime.date(1984, 6, 25)
ttl = env.timedelta("TTL") # => datetime.timedelta(0, 42)
log_level = env.log_level("LOG_LEVEL") # => logging.DEBUG
# providing a default value
enable_login = env.bool("ENABLE_LOGIN", False) # => True
enable_feature_x = env.bool("ENABLE_FEATURE_X", False) # => False
# parsing lists
gh_repos = env.list("GITHUB_REPOS") # => ['webargs', 'konch', 'ped']
coords = env.list("COORDINATES", subcast=float) # => [23.3, 50.0]
# parsing dicts
gh_repos_priorities = env.dict(
"GITHUB_REPO_PRIORITY", subcast_values=int
) # => {'webargs': 2, 'konch': 3}
支持类型
以下都是 Env
的类型转换方法:
env.str
env.bool
env.int
env.float
env.decimal
env.list
(接受可选的subcast
和delimiter
关键字参数)env.dict
(接受可选的subcast_keys
、subcast_values
和delimiter
关键字参数)env.json
env.datetime
env.date
env.time
env.timedelta
(假设值是秒的整数)env.url
env.uuid
env.log_level
env.path
(转换为pathlib.Path
)env.enum
(转换为在type
关键字参数中指定的任何枚举类型,接受可选的ignore_case
关键字参数)
读取 .env
文件
# .env
DEBUG=true
PORT=4567
在解析变量之前调用Env.read_env
。
from environs import Env
env = Env()
# Read .env into os.environ
env.read_env()
env.bool("DEBUG") # => True
env.int("PORT") # => 4567
读取特定文件
默认情况下,Env.read_env
将在当前目录中查找.env
文件,并在找不到.env
文件时向上递归,直到找到.env
文件。
您也可以读取特定文件
from environs import Env
with open(".env.test", "w") as fobj:
fobj.write("A=foo\n")
fobj.write("B=123\n")
env = Env()
env.read_env(".env.test", recurse=False)
assert env("A") == "foo"
assert env.int("B") == 123
处理前缀
# export MYAPP_HOST=lolcathost
# export MYAPP_PORT=3000
with env.prefixed("MYAPP_"):
host = env("HOST", "localhost") # => 'lolcathost'
port = env.int("PORT", 5000) # => 3000
# nested prefixes are also supported:
# export MYAPP_DB_HOST=lolcathost
# export MYAPP_DB_PORT=10101
with env.prefixed("MYAPP_"):
with env.prefixed("DB_"):
db_host = env("HOST", "lolcathost")
db_port = env.int("PORT", 10101)
变量扩展
# export CONNECTION_URL=https://${USER:-sloria}:${PASSWORD}@${HOST:-localhost}/
# export PASSWORD=secret
# export YEAR=${CURRENT_YEAR:-2020}
from environs import Env
env = Env(expand_vars=True)
connection_url = env("CONNECTION_URL") # =>'https://sloria:secret@localhost'
year = env.int("YEAR") # =>2020
验证
# export TTL=-2
# export NODE_ENV='invalid'
# export EMAIL='^_^'
from environs import Env
from marshmallow.validate import OneOf, Length, Email
env = Env()
# simple validator
env.int("TTL", validate=lambda n: n > 0)
# => Environment variable "TTL" invalid: ['Invalid value.']
# using marshmallow validators
env.str(
"NODE_ENV",
validate=OneOf(
["production", "development"], error="NODE_ENV must be one of: {choices}"
),
)
# => Environment variable "NODE_ENV" invalid: ['NODE_ENV must be one of: production, development']
# multiple validators
env.str("EMAIL", validate=[Length(min=4), Email()])
# => Environment variable "EMAIL" invalid: ['Shorter than minimum length 4.', 'Not a valid email address.']
延迟验证
默认情况下,在调用解析器方法对无效环境变量进行解析时将立即引发验证错误。为了延迟验证并引发包含所有无效变量组合错误消息的异常,请将eager=False
传递给Env
。在解析所有变量之后调用env.seal()
。
# export TTL=-2
# export NODE_ENV='invalid'
# export EMAIL='^_^'
from environs import Env
from marshmallow.validate import OneOf, Email, Length, Range
env = Env(eager=False)
TTL = env.int("TTL", validate=Range(min=0, max=100))
NODE_ENV = env.str(
"NODE_ENV",
validate=OneOf(
["production", "development"], error="NODE_ENV must be one of: {choices}"
),
)
EMAIL = env.str("EMAIL", validate=[Length(min=4), Email()])
env.seal()
# environs.EnvValidationError: Environment variables invalid: {'TTL': ['Must be greater than or equal to 0 and less than or equal to 100.'], 'NODE_ENV': ['NODE_ENV must be one of: production, development'], 'EMAIL': ['Shorter than minimum length 4.', 'Not a valid email address.']}
env.seal()
验证所有已解析变量,并阻止进一步解析(调用解析器方法将引发错误)。
URL方案
env.url()
通过schemes
参数支持非标准URL方案。
REDIS_URL = env.url(
"REDIS_URL", "redis://redis:6379", schemes=["redis"], require_tld=False
)
序列化
# serialize to a dictionary of simple types (numbers and strings)
env.dump()
# {'COORDINATES': [23.3, 50.0],
# 'ENABLE_FEATURE_X': False,
# 'ENABLE_LOGIN': True,
# 'GITHUB_REPOS': ['webargs', 'konch', 'ped'],
# 'GITHUB_USER': 'sloria',
# 'MAX_CONNECTIONS': 100,
# 'MYAPP_HOST': 'lolcathost',
# 'MYAPP_PORT': 3000,
# 'SHIP_DATE': '1984-06-25',
# 'TTL': 42}
定义自定义解析器行为
# export DOMAIN='http://myapp.com'
# export COLOR=invalid
from furl import furl
# Register a new parser method for paths
@env.parser_for("furl")
def furl_parser(value):
return furl(value)
domain = env.furl("DOMAIN") # => furl('https://myapp.com')
# Custom parsers can take extra keyword arguments
@env.parser_for("choice")
def choice_parser(value, choices):
if value not in choices:
raise environs.EnvError("Invalid!")
return value
color = env.choice("COLOR", choices=["black"]) # => raises EnvError
与Flask一起使用
# myapp/settings.py
from environs import Env
env = Env()
env.read_env()
# Override in .env for local development
DEBUG = env.bool("FLASK_DEBUG", default=False)
# SECRET_KEY is required
SECRET_KEY = env.str("SECRET_KEY")
在初始化您的应用程序之后加载配置。
# myapp/app.py
from flask import Flask
app = Flask(__name__)
app.config.from_object("myapp.settings")
对于本地开发,使用.env
文件来覆盖默认配置。
# .env
DEBUG=true
SECRET_KEY="not so secret"
注意:由于environs依赖于python-dotenv,因此flask CLI将自动读取.env和.flaskenv文件。
与Django一起使用
environs包含许多解析连接URL的辅助工具。要安装带有django支持的environs
pip install environs[django]
使用env.dj_db_url
、env.dj_cache_url
和env.dj_email_url
分别解析DATABASE_URL
、CACHE_URL
和EMAIL_URL
环境变量。
有关URL模式的更多详细信息,请参阅environs使用的以下项目。
基本示例
# myproject/settings.py
from environs import Env
env = Env()
env.read_env()
# Override in .env for local development
DEBUG = env.bool("DEBUG", default=False)
# SECRET_KEY is required
SECRET_KEY = env.str("SECRET_KEY")
# Parse database URLs, e.g. "postgres://localhost:5432/mydb"
DATABASES = {"default": env.dj_db_url("DATABASE_URL")}
# Parse email URLs, e.g. "smtp://"
email = env.dj_email_url("EMAIL_URL", default="smtp://")
EMAIL_HOST = email["EMAIL_HOST"]
EMAIL_PORT = email["EMAIL_PORT"]
EMAIL_HOST_PASSWORD = email["EMAIL_HOST_PASSWORD"]
EMAIL_HOST_USER = email["EMAIL_HOST_USER"]
EMAIL_USE_TLS = email["EMAIL_USE_TLS"]
# Parse cache URLS, e.g "redis://localhost:6379/0"
CACHES = {"default": env.dj_cache_url("CACHE_URL")}
对于本地开发,使用.env
文件来覆盖默认配置。
# .env
DEBUG=true
SECRET_KEY="not so secret"
有关更完整的示例,请参阅examples/
目录中的django_example.py。
为什么...?
为什么是环境变量?
为什么不是 os.environ
?
虽然os.environ
对于简单用例足够使用,但典型应用程序将需要一种操作和验证原始环境变量的方法。environs抽象了处理环境变量的常见任务。
environs将帮助您
- 将envvars转换为正确的类型
- 指定必需的envvars
- 定义默认值
- 验证envvars
- 解析列表和字典值
- 解析日期、日期时间和时间差
- 解析扩展变量
- 将配置序列化为JSON、YAML等。
为什么还要另一个库?
有许多优秀的Python库用于解析环境变量。实际上,environs公共API的大部分功劳归功于envparse和django-environ的作者。
environs旨在实现三个额外的目标
- 使扩展解析行为和开发插件变得容易。
- 利用由单独的库(marshmallow)提供的反序列化和验证功能。
- 清理冗余API。
请参阅此GitHub问题,其中详细说明了与envparse的具体差异。
许可证
MIT许可。有关更多详细信息,请参阅LICENSE文件。
项目详细信息
下载文件
下载适合您平台文件的文件。如果您不确定选择哪个,请了解有关安装包的更多信息。
源分布
构建分布
environs-11.0.0.tar.gz的哈希值
算法 | 哈希摘要 | |
---|---|---|
SHA256 | 069727a8f73d8ba8d033d3cd95c0da231d44f38f1da773bf076cef168d312ee8 |
|
MD5 | 69a3ccf9cae0d54a234301092ac49793 |
|
BLAKE2b-256 | f2133d448cfbed9f1baff5765f49434cd849501351f14fd3f09f0f2e9bd35322 |
environs-11.0.0-py3-none-any.whl的哈希值
算法 | 哈希摘要 | |
---|---|---|
SHA256 | e0bcfd41c718c07a7db422f9109e490746450da38793fe4ee197f397b9343435 |
|
MD5 | 7734fef44aae800d80caaaa1d4cde2e5 |
|
BLAKE2b-256 | 3f30ef8a3022e6cdcedfd7ba03ca88ab29e30334f8e958cdbf5ce120912397e8 |