|
前言
常见的应用配置方式有环境变量和配置文件,对于微服务应用,还会从配置中心加载配置,比如nacos、etcd等,有的应用还会把部分配置写在数据库中。此处主要记录从环境变量、.env文件、.ini文件、.yaml文件、.toml文件、.json文件读取配置。
ini文件
ini文件格式一般如下:
- [mysql]
- type = "mysql"
- host = "127.0.0.1"
- port = 3306
- username = "root"
- password = "123456"
- dbname = "test"
- [redis]
- host = "127.0.0.1"
- port = 6379
- password = "123456"
- db = "5"
复制代码 使用python标准库中的configparser可以读取ini文件。
- import configparser
- import os
- def read_ini(filename: str = "conf/app.ini"):
- """
- Read configuration from ini file.
- :param filename: filename of the ini file
- """
- config = configparser.ConfigParser()
- if not os.path.exists(filename):
- raise FileNotFoundError(f"File {filename} not found")
- config.read(filename, encoding="utf-8")
- return config
复制代码 config类型为configparser.ConfigParser,可以使用如下方式读取
- config = read_ini("conf/app.ini")
- for section in config.sections():
- for k,v in config.items(section):
- print(f"{section}.{k}: {v}")
复制代码 读取输出示例
- mysql.type: "mysql"
- mysql.host: "127.0.0.1"
- mysql.port: 3306
- mysql.username: "root"
- mysql.password: "123456"
- mysql.dbname: "test"
- redis.host: "127.0.0.1"
- redis.port: 6379
- redis.password: "123456"
- redis.db: "5"
复制代码 yaml文件
yaml文件内容示例如下:
- database:
- mysql:
- host: "127.0.0.1"
- port: 3306
- user: "root"
- password: "123456"
- dbname: "test"
- redis:
- host:
- - "192.168.0.10"
- - "192.168.0.11"
- port: 6379
- password: "123456"
- db: "5"
- log:
- directory: "logs"
- level: "debug"
- maxsize: 100
- maxage: 30
- maxbackups: 30
- compress: true
复制代码 读取yaml文件需要安装pyyaml
读取yaml文件的示例代码
- import yaml
- import os
- def read_yaml(filename: str = "conf/app.yaml"):
- if not os.path.exists(filename):
- raise FileNotFoundError(f"File {filename} not found")
- with open(filename, "r", encoding="utf-8") as f:
- config = yaml.safe_load(f.read())
- return config
-
- if __name__ == "__main__":
- config = read_yaml("conf/app.yaml")
- print(type(config))
- print(config)
复制代码 执行输出,可以看到config是个字典类型,通过key就可以访问到
- <class 'dict'>
- {'database': {'mysql': {'host': '127.0.0.1', 'port': 3306, 'user': 'root', 'password': '123456', 'dbname': 'test'}, 'redis': {'host': ['192.168.0.10', '192.168.0.11'], 'port': 6379, 'password': '123456', 'db': '5'}}, 'log': {'directory': 'logs', 'level': 'debug', 'maxsize': 100, 'maxage': 30, 'maxbackups': 30, 'compress': True}}
复制代码 toml文件
toml文件比较像yaml,但是不要求缩进格式。如果比较讨厌yaml的缩进问题,那么可以考虑下使用toml。一个简单的toml文件示例如下:
- [database]
- dbtype = "mysql"
- [database.mysql]
- host = "127.0.0.1"
- port = 3306
- user = "root"
- password = "123456"
- dbname = "test"
- [database.redis]
- host = ["192.168.0.10", "192.168.0.11"]
- port = 6379
- password = "123456"
- db = "5"
- [log]
- directory = "logs"
- level = "debug"
复制代码 如果python版本高于3.11,其标准库tomllib就可以读取toml文件。读取toml文件的第三方库也有很多,个人一般使用toml
读取toml文件的示例代码
- import tomllib # python version >= 3.11
- import toml
- import os
- def read_toml_1(filename: str = "conf/app.toml"):
- """
- Read configuration from toml file using tomllib that is python standard package.
- Python version >= 3.11
- """
- if not os.path.exists(filename):
- raise FileNotFoundError(f"File {filename} not found")
- with open(filename, "rb") as f:
- config = tomllib.load(f)
- return config
-
- def read_toml_2(filename: str = "conf/app.toml"):
- """
- Read configuration from toml file using toml package.
- """
- if not os.path.exists(filename):
- raise FileNotFoundError(f"File {filename} not found")
-
- with open(filename, "r" ,encoding="utf-8") as f:
- config = toml.load(f)
- return config
-
- if __name__ == "__main__":
- config = read_toml_1("conf/app.yaml")
- # config = read_toml_2("conf/app.yaml")
- print(type(config))
- print(config)
复制代码 执行输出,无论使用tomllib或toml,返回的都是dict类型,都可以直接使用key访问。
- <class 'dict'>
- {'database': {'mysql': {'host': '127.0.0.1', 'port': 3306, 'user': 'root', 'password': '123456', 'dbname': 'test'}, 'redis': {'host': ['192.168.0.10', '192.168.0.11'], 'port': 6379, 'password': '123456', 'db': '5'}}, 'log': {'directory': 'logs', 'level': 'debug', 'maxsize': 100, 'maxage': 30, 'maxbackups': 30, 'compress': True}}
复制代码 json文件
使用标准库json即可读取json文件,json配置文件示例:
- {
- "database": {
- "mysql": {
- "host": "127.0.0.1",
- "port": 3306,
- "user": "root",
- "password": "123456",
- "dbname": "test"
- },
- "redis": {
- "host": [
- "192.168.0.10",
- "192.168.0.11"
- ],
- "port": 6379,
- "password": "123456",
- "db": "5"
- }
- },
- "log": {
- "level": "debug",
- "dir": "logs"
- }
- }
复制代码 解析的示例代码如下
- import json
- import os
- def read_json(filename: str = "conf/app.json") -> dict:
- """
- Read configuration from json file using json package.
- """
- if not os.path.exists(filename):
- raise FileNotFoundError(f"File {filename} not found")
- with open(filename, "r", encoding="utf-8") as f:
- config = json.load(f)
- return config
-
- if __name__ == "__main__":
- config = read_json("conf/app.yaml")
- print(type(config))
- print(config)
复制代码 执行输出
- <class 'dict'>
- {'database': {'mysql': {'host': '127.0.0.1', 'port': 3306, 'user': 'root', 'password': '123456', 'dbname': 'test'}, 'redis': {'host': ['192.168.0.10', '192.168.0.11'], 'port': 6379, 'password': '123456', 'db': '5'}}, 'log': {'level': 'debug', 'dir': 'logs'}}
复制代码 .env文件
从.env文件读取键值对配置,并将它们添加到环境变量中,添加后可以使用os.getenv()获取。
读取.env文件需要安装第三方库
- pip install python-dotenv
复制代码 .env文件示例
- MYSQL_HOST="127.0.0.1"
- MYSQL_PORT=3306
- MYSQL_USERNAME="root"
- MYSQL_PASSWORD="123456"
- MYSQL_DATABASE="test"
复制代码 示例代码
- import os
- import dotenv
- def read_dotenv(filename: str = "conf/.env"):
- if not os.path.exists(filename):
- raise FileNotFoundError(f"File {filename} not found")
- load_dotenv(dotenv_path=filename, encoding="utf-8", override=True)
- config = dict(os.environ)
- return config
- if __name__ == "__main__":
- config = read_json("conf/app.yaml")
- for k,v in config.items():
- if k.startswith("MYSQL_"):
- print(f"{k}: {v}")
复制代码 读取环境变量
在标准库os中有以下常用的和环境变量相关的方法,具体可参考官方文档:https://docs.python.org/zh-cn/3/library/os.html
- os.environ,一个mapping对象,其中键值是代表进程环境的字符串。例如 environ["HOME"]
- # example
- import os
- config = dict(os.environ)
- for k,v in config.items():
- print(k,v)
复制代码
- os.getenv(key, default=None)。如果环境变量 key 存在则将其值作为字符串返回,如果不存在则返回 default。
- os.putenv(key, value)。设置环境变量,官方文档推荐直接修改os.environ。例如:os.putenv("MYSQL_HOST", "127.0.0.1")
- os.unsetenv(key)。删除名为 key 的环境变量,官方文档推荐直接修改os.environ。例如:os.unsetenv("MYSQL_HOST")
综合示例
一般来说配置解析相关代码会放到单独的包中,配置文件也会放到单独的目录,这里给个简单的示例。
目录结构如下,conf目录存放配置文件,pkg/config.py用于解析配置,main.py为程序入口。
- .
- ├── conf
- │ ├── app.ini
- │ ├── app.json
- │ ├── app.toml
- │ └── app.yaml
- ├── main.py
- └── pkg
- ├── config.py
- └── __init__.py
复制代码 pkg/__init__.py文件为空,pkg/config.py内容如下:
- import configparser
- import os
- import yaml
- import tomllib
- import json
- import abc
- from dotenv import load_dotenv
- class Configer(metaclass=abc.ABCMeta):
- def __init__(self, filename: str):
- self.filename = filename
- @abc.abstractmethod
- def load(self):
- raise NotImplementedError(f"subclass must implement this method")
-
- def file_exists(self):
- if not os.path.exists(self.filename):
- raise FileNotFoundError(f"File {self.filename} not found")
- class IniParser(Configer):
- def __init__(self, filename: str):
- super().__init__(filename)
- def load(self):
- super().file_exists()
- config = configparser.ConfigParser()
- config.read(self.filename, encoding="utf-8")
- return config
- class YamlParser(Configer):
- def __init__(self, filename: str):
- super().__init__(filename)
- def load(self):
- super().file_exists()
- with open(self.filename, "r", encoding="utf-8") as f:
- config = yaml.safe_load(f.read())
- return config
- class TomlParser(Configer):
- def __init__(self, filename: str):
- super().__init__(filename)
- def load(self):
- super().file_exists()
- with open(self.filename, "rb") as f:
- config = tomllib.load(f)
- return config
-
- class JsonParser(Configer):
- def __init__(self, cfgtype: str, filename: str = None):
- super().__init__(cfgtype, filename)
- def load(self):
- super().file_exists()
- with open(self.filename, "r", encoding="utf-8") as f:
- config = json.load(f)
- return config
-
- class DotenvParser(Configer):
- def __init__(self, filename: str = None):
- super().__init__(filename)
- def load(self):
- super().file_exists()
- load_dotenv(self.filename, override=True)
- config = dict(os.environ)
- return config
复制代码 main.py示例:
- from pkg.config import TomlParser
- config = TomlParser("conf/app.toml")
- print(config.load())
复制代码 执行输出
- {'database': {'dbtype': 'mysql', 'mysql': {'host': '127.0.0.1', 'port': 3306, 'user': 'root', 'password': '123456', 'dbname': 'test'}, 'redis': {'host': ['192.168.0.10', '192.168.0.11'], 'port': 6379, 'password': '123456', 'db': '5'}}, 'log': {'directory': 'logs', 'level': 'debug'}}
复制代码 来源:https://www.cnblogs.com/XY-Heruo/p/17953418
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作! |
|