PyYAML中自定义tag标签获取环境变量值
2022/4/6 6:19:28
本文主要是介绍PyYAML中自定义tag标签获取环境变量值,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
前言
YAML常用于配置文件,当配置文件中需要配置一些用户名密码时,直接写在YAML文件并上传到代码仓库中则很容易造成密码泄露。
不幸的是,前一段时间我们组的自动化代码就被检测到了密码泄露,被通知整改。
解决的方法有两种:
- 配置文件仅本地使用,不传到代码仓库中
- 将密码配置到执行机器的环境变量中,在YAML中使用特殊标记表示读取一个环境变量
我们可以使用自定义tag来实现这种功能。在PyYAML中一种tag标识一种类型,常见的tag有:
!!null | None |
---|---|
!!bool | bool |
!!int | int |
!!float | float |
!!binary | bytes |
!!timestamp | datetime.datetime |
!!omap, !!pairs | list of pairs |
!!set | set |
!!str | str |
!!seq | list |
!!map | dict |
自定义tag
我们自定义一个新的tag, !env
, 并编写一个对应的处理函数(PyYAML中称为constructor构造器),代码如下:
demo.yaml文件
user: !env ${USER} # 表示环境变量USER,即当前用户名
Python文件如下:
import os import yaml # 需要pip install pyyaml def env_var_constructor(loader, node): value = loader.construct_scalar(node) # PyYAML loader的固定方法,用于根据当前节点构造一个变量值 var_name = value.strip('${} ') # 去除变量值(例如${USER})前后的特殊字符及空格 return os.getenv(var_name, value) # 尝试在环境变量中获取变量名(如USER)对应的值,获取不到使用默认值value(即原来的${USER}) yaml.SafeLoader.add_constructor('!env', env_var_constructor) # 为SafeLoader添加新的tag和构造器 with open('demo.yml') as f: print(yaml.safe_load(f)) # 打开文件并使用SafeLoader加载文件内容
结果如下:
{'user': 'superhin'}
为tag分配匹配模式
此时YAML文件中环境变量只能使用强制类型声明!env ${变量名}
来使用,如果想直接使用${变量名}
来使用则需要为该tag指定一种正则匹配模式,即识别到类似${变量名}
格式时自动使用!env这个tag。
demo.yaml文件
user: !env ${USER} # 表示环境变量USER,即当前用户名 path: ${PATH} # 期望可以直接使用
import os import re import yaml pattern = re.compile('\${\w+}') # 匹配 ${一个或多个字母或数字} def env_var_constructor(loader, node): value = loader.construct_scalar(node) var_name = value.strip('${} ') return os.getenv(var_name, value) yaml.SafeLoader.add_constructor('!env', env_var_constructor) # 添加新tag即对应的构造器 yaml.SafeLoader.add_implicit_resolver('!env', pattern, None) # 为tag指定一种正则匹配 with open('demo.yml') as f: print(yaml.safe_load(f)) # 打开文件并使用SafeLoader加载文件内容
运行结果如下
{'user': 'superhin', 'path': '...<省略>'}
一个节点使用多个变量
如果我们想要在一个节点中使用多个变量,如
demo.yml内容
user: !env ${USER} path: ${PATH} msg: 当前用户名 ${USER} 系统路径 ${PATH}
则需要对节点值value(字符串格式)进行逐个替换。
首先我们需要修改我们的匹配模式,允许${变量}前后可以拥有多个任意字符
pattern = re.compile('.*(\${\w+}).*') # 前后可以拥有多个任意字符,使用小括号分组只取当前变量${变量名}内容
完整代码如下:
import os import re import yaml pattern = re.compile('.*?(\${\w+}).*?') # 前后可以拥有多个任意字符,使用小括号分组只取当前变量${变量名}内容,`?`表示非贪婪匹配。 def env_var_constructor(loader, node): value = loader.construct_scalar(node) for item in pattern.findall(value): # 遍历所有匹配到到${变量名}的变量, 如${USER} var_name = item.strip('${} ') # 如,USER value = value.replace(item, os.getenv(var_name, item)) # 用环境变量中取到的对应值替换当前变量 return value # 如superin替换${USER},取不到则使用原值${USER} yaml.SafeLoader.add_constructor('!env', env_var_constructor) yaml.SafeLoader.add_implicit_resolver('!env', pattern, None) with open('demo.yml') as f: print(yaml.safe_load(f))
运行结果如下:
{'user': 'superhin', 'path': '...<省略>', 'msg': '当前用户名 superhin 系统路径 ...<省略>'}
参考:PyYAML官方文档
这篇关于PyYAML中自定义tag标签获取环境变量值的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2025-01-04敏捷管理与看板工具:提升研发、设计、电商团队工作效率的利器
- 2025-01-04智慧养老管理工具如何重塑养老生态?
- 2025-01-04如何打造高绩效销售团队:工具与管理方法的结合
- 2025-01-04解决电商团队协作难题,在线文档工具助力高效沟通
- 2025-01-04春节超市管理工具:解锁高效运营与顾客满意度的双重密码
- 2025-01-046种主流销售预测模型:如何根据场景选用最佳方案
- 2025-01-04外贸服务透明化:增强客户信任与合作的最佳实践
- 2025-01-04重新定义电商团队协作:在线文档工具的战略作用
- 2025-01-04Easysearch Java SDK 2.0.x 使用指南(三)
- 2025-01-04百万架构师第八课:设计模式:设计模式容易混淆的几个对比|JavaGuide