Jonnyan的原创笔记
alpine
alpine里python安装mssql笔记
Alpine linux如何配置和管理自定义服务
windows
window server2012远程授权重置
window获取本机所有IP
window远程桌面RDP加速方案
远程监控 Win10 资源占用
windows 下 mysql 区分大小写敏感问题
window下navicat无限试用脚本
Linux
解决openvpn的CRL has expired笔记
centos7.x配置时间服务器(chrony)
centos7.x下安装wireguard
解决influxdb的log日志输出位置
保存 iptable 规则并开机自动加载 | SA-Logs
kafka笔记
kafka的server.properties 配置文件参数说明
CentOS 和 RedHat 下 8 个最常用的 YUM 库
外网IP查询网站
VirtualBox Ubuntu20/centos7 命令行如何扩容分区磁盘
如何备份sqlite数据库
yum 安装 redis5/mq/consul
centos7.x 安装 docker-ce
zabbix4.2 的 yum+mariadb 方式部署安装
如何在 Linux 中查找最大的 10 个文件
mongodb 备份与还原操作
Linux 高频工具快速教程
yum 安装 influxdb/telegraf
ubuntu 14.04/16.04/18.04 yum 安装 zabbix-agent 教程
逃不掉的 mysql 数据库安装方式大全 yum rpm 源码
VIM 配置入门
find 命令结合 cp bash mv 命令使用的 4 种方式
Tomcat nginx log 日志按天分割切割
linux 和 pycharm 下终端彩色打印输出
centos5/6/7 下 yum 安装 zabbix-agent(被控端)
shell 脚本头,#!/bin/sh 与 #!/bin/bash 的区别.
electerm/tabby在执行screen命令后不显示滚动条
python
python virtualenv笔记
python配置文件INI/TOML/YAML/ENV的区别
python限制函数的执行时间
python里and和or的理解
SQLite is not a toy database | Anton Zhiyanov
四行代码实现 Python 管道 - Aber's blog
systemd管理虚拟环境Django+uwsgi+nginx配置教程
Linux shell命令创建python django用户
nginx子路径下反代运行多个django
django web 应用 runserver 模式下 cpu 占用高解决办法
解决 pip 安装模块报错 Cannot fetch index base URL http://pypi.python.org/simple/
docker
仅在首次启动时在Docker容器中运行命令
Docker多平台架构镜像构建
解决cadvisor监控内存值与docker stats命令值不一致问题
docker 清理指定日期之前的镜像
docker 部署 graylog 使用教程
docker 一键搭建 zerotier-moon 节点
alpine的docker镜像安装mysql/mariadb/redis
dockerfile 多阶段构建参考
Warning: Stopping docker.service, but it can still be activated by: docker.socket
nginx
Nginx限制并发连接数与下载速度
nginx仅允许域名访问禁止IP访问
Nginx 强制跳转 Https
nginx强制跳转https无限301循环问题
万字总结,带你全面系统的认识 Nginx
linux 下编译安装 nginx 完整版
解决 nginx 同端口强制跳转 https 配置 ssl 证书问题
nginx 关闭日志功能 access_log 关闭
基于 nginx 的 token 认证
杂记
小米手机MIUI12安装Google服务
使用sphinx+markdown+readthedocs+github来编写文档
N1由armbian直刷openwrt
N1安装docker版本的openwrt做旁路由
NUC10 i3/i5/i7系列开启局域网wol唤醒
威联通qnap安装nginx
威联通qnap配置开机自启动项
telegram bot python使用示例教程
两款paste临时文本分享平台
docker部署微力同步(verysync)
Android和IOS自部署通知程序
苹果M1如何科学上网
M1 mac iterm2配置lrzsz命令
漫威轮播
网件XR500/R7800刷机
DIY 编译 openwrt 固件
苹果 mac 版微软官方远程连接工具下载 Microsoft Remote Desktop For Mac
wireguard 实现 peer 互联, NAT to NAT
学习本来的样子
解决 aws ec2 的 centos7 设置时区无效
redis 问题优化
N1 如何完美刷入 armbian 系统教程
v2rayN 的 pac 简单规则
博客园 markdown 使用折叠语法和颜色标签
十年感悟之 python 之路
在浏览器输入 URL 回车后发生了什么?
grafana 里 prometheus 查询语法
国内开源镜像站点汇总
解决阿里云部署 office web apps ApplicationFailedException 报错问题
解决 mac 休眠睡眠异常耗电方法
jira 集成 fisheye 代码深度查看工具安装绿色版
阿里云 ecs 开启 x11 图形化桌面
markdown 完整语法规范 3.0 + 编辑工具介绍
pycharm 重置设置,恢复默认设置
[已解决]window 下 Can't connect to MySQL server on'localhost' (10061) 与无法启动 MYSQL 服务”1067 进程意外终止”
解决 xshell6 评估过期, 需采购问题
[已解决]pycharm 报错: AttributeError: module 'pip' has no attribute 'main'
[已解决]windows 下 python3.x 与 python2.7 共存版本 pip 使用报错问题
云策文档think配置https教程
机器监控告警
zabbix
yum / 编译安装 Zabbix 5.0 LTS
zabbix 监控 AWS-SQS 队列
Zabbix-agent 端配置文件说明
Prometheus+grafana
prometheus+grafana安装和配置
node_exporter主机监控
cadvisor容器监控
redis_exporter监控
rabbitmq_exporter监控
consul_exporter监控
windows_exporter
Open-Falcon
falcon 数据丢失处理方法参考
日志监控告警
graylog
graylog 通过 python 实现钉钉 / 微信 / webhook 告警
loki+grafana
Loki简介
Loki安装
Loki查询语法
grafana面板pannel语法
内网穿透
frp
zerotier
zerotier充当网关实现内网互联,访问其它节点内网
一分钟自建zerotier-plant
nps
anylink
N2N
本文档发布于https://mrdoc.fun
-
+
首页
python配置文件INI/TOML/YAML/ENV的区别
> 机翻,如有差异,请查看原文地址 https://hackersandslackers.com/simplify-your-python-projects-configuration/ 有一天,我们每个人都会死。也许我们会光荣地走出去,过上幸福的生活后盖章。当我们吸取了无法再继续的无用职业的最后一根稻草时,我们中的一些人可能会内心死亡。无论您的死亡是肉体死亡还是精神死亡,都可以肯定有一件事:您的雇主和同事会认为您永远对他们死。 办公文化使奇怪的成语永存,我最喜欢的是永恒的“被公共汽车撞”的陈词滥调。多年来,每家公司都有相当一部分经验丰富的员工,他们积累了宝贵的知识。随着公司发现自己越来越依赖这些贡献者,组织上的谢意开始转向一种偏执狂。没有人会怀疑:“ _如果我们最好的员工被公交车撞到怎么办?_ 我感谢一个组织的诗意正义,在剥削员工后无奈。也就是说,还有其他原因可确保您编写的代码易于他人阅读和使用。如果计划构建可继续运行的软件,则需要从逻辑上构建应用程序开始。让我们从第一个方框开始:项目配置。 我们可以使用许多文件类型来存储和访问整个项目中的重要变量。诸如**ini**,**YAML**或what-have 等文件类型都具有在结构化(或非结构化)层次结构中存储信息的独特方式。根据项目的性质,这些文件结构中的每一个都可以很好地为您服务或妨碍您的工作。我们将研究所有这些选项的优势,以及如何使用其相应的Python库解析这些配置。 ### 认识竞争者 格式化的方法不止一种,但是在现代软件中格式化配置文件的方法甚至更多。我们将介绍一些用于处理项目配置的最常见文件格式(_**ini**_,_**toml**_,_**yaml**_,_**conf**_,_**json**_,_**env**_)和解析它们的Python库。 INI文件 ----- **ini**文件可能是我们可以使用的最直接的配置文件。**ini**文件非常适合较小的项目,主要是因为这些文件仅支持1级深的层次结构。**ini**文件本质上是平面文件,但变量可以属于组。下面的示例演示了具有相同主题的变量如何可以归入一个通用标题,例如_[DATABASE]_或_[LOGS]_: > `config.ini` ```config.ini [APP] ENVIRONMENT = development DEBUG = False [DATABASE] USERNAME: root PASSWORD: p@ssw0rd HOST: 127.0.0.1 PORT: 5432 DB: my_database [LOGS] ERRORS: logs/errors.log INFO: data/info.log [FILES] STATIC_FOLDER: static TEMPLATES_FOLDER: templates ``` 这种结构无疑使人们更容易理解事物,但是这种结构的实用性超出了美学。让我们使用Python的[configparser](https://docs.python.org/3/library/configparser.html)库解析此文件,以了解实际情况。我们首先将**test.ini**的内容**保存**到一个名为**config**的变量中: > `config.py` ``` import configparser config = configparser.ConfigParser() config.read('~/Desktop/config.ini') ``` 调用`read()`上**的ini**文件确实比普通商店的数据更为; 实际上,我们的**config**变量现在是其自己的唯一数据结构,从而允许我们使用各种方法来读取和写入配置值。尝试跑步`print(config)`看看自己: ``` <configparser.ConfigParser object at 0x10e58c390> ``` 存在配置文件只是为了提取值。**configparser**允许我们以多种方式执行此操作。下面的每一行都返回`127.0.0.1`: ``` config.get('DATABASE', 'HOST') config['DATABASE']['HOST'] ``` 对于期望接收特定数据类型的值,**configparser**有许多类型检查方法来检索我们正在寻找的数据结构中的值。该命令`config.getboolean('APP', 'DEBUG')`将正确返回布尔值**False**,而不是一个字符串“ False”,这显然对我们的应用程序有问题。如果将我们的值`DEBUG`设置为布尔值以外的值,`config.getboolean()`则会抛出错误。**configparser**还有许多其他类型检查方法,例如`getint()`,`getfloat()`等等。 **configparser**的功能 并不止于此。我们可以详细介绍该库编写新配置值,检查键是否存在等的能力,但我们不可以。 TOML文件 ------ 乍看起来,**TOML**文件似乎与**ini**文件共享_某些_语法相似之处,但支持更广泛的数据类型以及值本身之间的关系。**TOML**文件还迫使我们提前更清楚地了解数据结构,而不是像**configparser**那样_在_解析_后_确定它们。 在Python中解析TOML文件由一个适当地称为[toml](https://pypi.org/project/toml/)的库处理,在我们去那里之前,让我们看看TOML的炒作是什么。 ### TOML变量类型 **TOML**文件通过键/值对定义变量,方式与**ini**文件类似。**Ť** HESE对被称为_密钥_。但是,与**ini**文件不同,**TOML**希望将键的值存储为打算用作键的数据类型。打算解析为字符串的变量_必须_作为值存储在引号中,而布尔值必须存储为原始的**true**或**false**值。这消除了我们配置的许多歧义:我们不需要诸如`getboolean()`TOML文件之类的方法。 **TOML**文件可以支持令人印象深刻的变量类型目录。TOML支持的一些更令人印象深刻的变量类型包括**DateTime**,**本地时间**,**数组**,**float**甚至**十六进制值**: > `config.toml` ``` [project] name: "Faceback" description: "Powerful AI which renders the back of somebody's head, based on their face." version: "1.0.0" updated: 1979-05-27T07:32:00Z author = "Todd Birchard" ... ``` ### TOML文件结构 TOML文件中带括号的部分称为**表**。**密钥**可以存在于表的内部或外部,如下面的示例所示。您会注意到,这些并不是TOML文件中仅有的两个元素: > `config.toml` ``` # Keys title = "My TOML Config" # Tables [project] name = "Faceback" description = "Powerful AI which renders the back of somebody's head, based on their face." version = "1.0.0" updated = 1979-05-27T07:32:00Z author = "Todd Birchard" [database] host = "127.0.0.1" password = "p@ssw0rd" port = 5432 name = "my_database" connection_max = 5000 enabled = true # Nested `tables` [environments] [environments.dev] ip = "10.0.0.1" dc = "eqdc10" [environments.staging] ip = "10.0.0.2" dc = "eqdc10" [environments.production] ip = "10.0.0.3" dc = "eqdc10" # Array of Tables [[testers]] id = 1 username = "JohnCena" password = "YouCantSeeMe69" [[testers]] id = 3 username = "TheRock" password = "CantCook123" ``` 如表中所示,TOML支持**“嵌套表”**的概念,该`[environments]`表后面带有多个子表。通过使用点符号,我们能够创建表的关联,这意味着它们是同一元素的不同实例。 同样有趣的是概念**“表列”,**它做什么用发生`[[testers]]`。双括号中的表会自动添加到数组中,其中数组中的每个项目都是具有相同名称的表。可视化此处发生情况的最佳方法是使用JSON等价物: ``` { "testers": [ { "id": 1, "username": "JohnCena", "password": "YouCantSeeMe69" }, { "id": 2, "username": "TheRock", "password": "CantCook123" } ] } ``` ### 解析TOML 足够使用TOML作为标准,让我们获取数据: ``` import toml config = toml.load('/Users/toddbirchard/Desktop/config.toml') print(config) ``` 加载**TOML**文件立即返回字典: ``` {'title': 'My TOML Config', 'project': {'name': 'Faceback', 'description': "Powerful AI which renders the back of somebody's head, based on their face.", 'version': '1.0.0', 'updated': datetime.datetime(1979, 5, 27, 7, 32, tzinfo=<toml.tz.TomlTz object at 0x107b82390>), 'author': 'Todd Birchard'}, 'database': {'host': '127.0.0.1', 'password': 'p@ssw0rd', 'port': 5432, 'name': 'my_database', 'connection_max': 5000, 'enabled': True}, 'environments': {'dev': {'ip': '10.0.0.1', 'dc': 'eqdc10'}, 'staging': {'ip': '10.0.0.2', 'dc': 'eqdc10'}, 'production': {'ip': '10.0.0.3', 'dc': 'eqdc10'}}, 'testers': [{'id': 1, 'username': 'JohnCena', 'password': 'YouCantSeeMe69'}, {'id': 1, 'username': 'TheRock', 'password': 'CantCook123'}]} ``` 从**config**抓取值就像使用任何字典一样容易: ``` # Retrieving a dictionary config['project'] config.get('project') # Retrieving a value config['project']['author'] config.get('project').get('author') ``` YAML配置 ------ **YAML**文件格式已经成为配置的人群首选,大概是因为它们易于阅读。那些熟悉YAML规范的人会告诉您,YAML _远_不是一种优雅的文件格式,但这似乎并没有阻止任何人。 **YAML**文件利用空格来定义变量层次结构,这似乎引起了许多开发人员的共鸣。查看示例YAML配置可能是什么样的: > `config.yaml` ``` appName: appName logLevel: WARN AWS: Region: us-east-1 Resources: EC2: Type: "AWS::EC2::Instance" Properties: ImageId: "ami-0ff8a91507f77f867" InstanceType: t2.micro KeyName: testkey BlockDeviceMappings: - DeviceName: /dev/sdm Ebs: VolumeType: io1 Iops: 200 DeleteOnTermination: false VolumeSize: 20 Lambda: Type: "AWS::Lambda::Function" Properties: Handler: "index.handler" Role: Fn::GetAtt: - "LambdaExecutionRole" - "Arn" Runtime: "python3.7" Timeout: 25 TracingConfig: Mode: "Active" routes: admin: url: /admin template: admin.html assets: templates: /templates static: /static dashboard: url: /dashboard template: dashboard.html assets: templates: /templates static: /static account: url: /account template: account.html assets: templates: /templates static: /static databases: cassandra: host: example.cassandra.db username: user password: password redshift: jdbcURL: jdbc:redshift://<IP>:<PORT>/file?user=username&password=pass tempS3Dir: s3://path/to/redshift/temp/dir/ redis: host: hostname port: port-number auth: authentication db: databaseconfig.yaml ``` 显而易见,YAML配置_易于编写和理解_。上面的YAML文件能够完成我们在TOML文件中看到的相同类型的复杂层次结构。但是,我们不需要显式设置变量数据类型,也不需要花时间来理解诸如**表**或**表****数组之类的**概念。可以轻易地辩称,YAML的易用性并不能证明其缺点。不要花太多时间考虑这个问题:我们在这里谈论配置文件。 我认为我们都可以同意的一点是,YAML肯定比JSON配置更胜一筹。这是与JSON文件相同的配置: > `config.json` ``` { "appName": "appName", "logLevel": "WARN", "AWS": { "Region": "us-east-1", "Resources": { "EC2": { "Type": "AWS::EC2::Instance", "Properties": { "ImageId": "ami-0ff8a91507f77f867", "InstanceType": "t2.micro", "KeyName": "testkey", "BlockDeviceMappings": [ { "DeviceName": "/dev/sdm", "Ebs": { "VolumeType": "io1", "Iops": 200, "DeleteOnTermination": false, "VolumeSize": 20 } } ] } }, "Lambda": { "Type": "AWS::Lambda::Function", "Properties": { "Handler": "index.handler", "Role": { "Fn::GetAtt": [ "LambdaExecutionRole", "Arn" ] }, "Runtime": "python3.7", "Timeout": 25, "TracingConfig": { "Mode": "Active" } } } } }, "routes": { "admin": { "url": "/admin", "template": "admin.html", "assets": { "templates": "/templates", "static": "/static" } }, "dashboard": { "url": "/dashboard", "template": "dashboard.html", "assets": { "templates": "/templates", "static": "/static" } }, "account": { "url": "/account", "template": "account.html", "assets": { "templates": "/templates", "static": "/static" } } }, "databases": { "cassandra": { "host": "example.cassandra.db", "username": "user", "password": "password" }, "redshift": { "jdbcURL": "jdbc:redshift://<IP>:<PORT>/file?user=username&password=pass", "tempS3Dir": "s3://path/to/redshift/temp/dir/" }, "redis": { "host": "hostname", "port": "port-number", "auth": "authentication", "db": "database" } } } ``` 告诉我一个比YAML更喜欢JSON的人,我将向您展示一个受虐狂,否认他们对AWS的供应商锁定。 ### 在Python中解析YAML 我建议使用[Python _Confuse_库](https://github.com/sampsyo/confuse)(一个软件包名称,一定会引起公司信息安全团队的注意)。 **Confuse**允许我们与YAML文件进行交互,几乎与JSON进行交互,除了`.get()`在遍历树层次结构结束时指定的例外外,如下所示: ``` config = confuse.Configuration('MyApp', __name__) config['AWS']['Lambda']['Runtime'].get() ``` **.get()**可以接受数据类型值,例如_int。_这样做可以确保我们获得的值实际上是我们所期望的模式,这是一个很好的功能。 #### 验证者 [Confuse的文档](https://confuse.readthedocs.io/en/latest/)详细介绍了从YAML文件中提取的值的其他验证方法。方法,如`as_filename()`,`as_number()`和`as_str_seq()`基本上做你希望他们到什么。 #### CLI配置 Confuse还进入了构建CLI的领域,允许我们使用YAML文件来通知可传递给CLI的参数及其潜在值: ``` config = confuse.Configuration('myapp') parser = argparse.ArgumentParser() parser.add_argument('--foo', help='a parameter') args = parser.parse_args() config.set_args(args) print(config['foo'].get()) ``` 您可以在这里做很多事情。 .ENV文件 ------ 环境变量是一种将敏感信息保持在项目代码库之外的好方法。我们可以用多种不同的方式存储环境变量,最简单的方法是通过命令行: ``` $ export MY_VARIABLE=AAAAtpl%2Bkvro%2BoQ9wRg77VUEpQv%2F ``` 只要您当前的终端会话处于打开状态,以这种方式存储的变量将一直存在,因此在测试之外对我们没有多大帮助。如果我们要`MY_VARIABLE`坚持下去,可以将以上`export`行添加到**.bash_profile**(或等效文件)中,以确保`MY_VARIABLE`在系统范围内始终存在。 特定于项目的变量更适合**驻留**在我们项目目录中的**.env**文件。为了上帝的爱,请勿将这些文件提交给GITHUB。 假设我们有一个**.env**文件,**其中**包含与项目相关的变量,如下所示: ``` FLASK_ENV=development FLASK_APP=wsgi.py COMPRESSOR_DEBUG=True STATIC_FOLDER=static TEMPLATES_FOLDER=templates ``` .env 现在,我们可以使用内置的Python提取这些值`os.environ`: > `config.py` ``` """App configuration.""" from os import environ class Config: """Set configuration vars from .env file.""" # General Config SECRET_KEY = environ.get('SECRET_KEY') FLASK_APP = environ.get('FLASK_APP') FLASK_ENV = environ.get('FLASK_ENV') # Flask-Assets LESS_BIN = environ.get('LESS_BIN') ASSETS_DEBUG = environ.get('ASSETS_DEBUG') LESS_RUN_IN_DEBUG = environ.get('LESS_RUN_IN_DEBUG') ``` 随便使用您想要的 -------- 显然,有很多方法可以在Python中设置环境和项目变量。我们可能会花费一整天的时间来剖析配置文件类型的利弊。这是我们肯定不想过分思考的生活的一个方面。 此外,我需要反思自己的生活。我只写了两千个关于配置文件的利弊的词,在意识到自己的生活毫无意义之前,我宁愿忘记这些词。
Jonny
2021年1月15日 10:12
693
转发文档
收藏文档
上一篇
下一篇
手机扫码
复制链接
手机扫一扫转发分享
复制链接
【腾讯云】爆款2核2G4M云服务器一年45元,企业首购最高获赠300元京东卡
【腾讯云】爆款2核2G4M云服务器一年45元,企业首购最高获赠300元京东卡
Markdown文件
Word文件
PDF文档
PDF文档(打印)
分享
链接
类型
密码
更新密码
有效期