Python中如何优雅地读取并支持运行时更改的配置文件?
本来选的 python 节点,
可能因为"大家", “都是”, “怎样” “?” 这些关键字, 被移动到调查节点了
有个需求是可能会在运行中修改配置文档, 然后其他同样引用了该配置的模块也能拿到新的值
代码在原帖内
Python中如何优雅地读取并支持运行时更改的配置文件?
本来选的 python 节点,
可能因为"大家", “都是”, “怎样” “?” 这些关键字, 被移动到调查节点了
有个需求是可能会在运行中修改配置文档, 然后其他同样引用了该配置的模块也能拿到新的值
代码在原帖内
缓存中读取,避免脏读即可
用 importlib.reload 配合单例模式来热更新配置最直接。下面这个 ConfigManager 类能搞定:
import importlib
import threading
from typing import Any, Dict
class ConfigManager:
_instance = None
_lock = threading.Lock()
def __new__(cls):
with cls._lock:
if cls._instance is None:
cls._instance = super().__new__(cls)
cls._instance._config_module = None
cls._instance._config_dict = {}
cls._instance._load_config()
return cls._instance
def _load_config(self):
"""加载或重新加载配置文件"""
try:
# 假设配置文件是 config.py
config_module = importlib.import_module('config')
if self._config_module:
importlib.reload(config_module)
else:
self._config_module = config_module
# 提取所有大写配置项
self._config_dict = {
key: getattr(config_module, key)
for key in dir(config_module)
if key.isupper() and not key.startswith('_')
}
except ImportError:
# 处理配置文件不存在的情况
self._config_dict = {}
def get(self, key: str, default: Any = None) -> Any:
"""获取配置值"""
return self._config_dict.get(key, default)
def reload(self):
"""重新加载配置文件"""
with self._lock:
self._load_config()
def all_configs(self) -> Dict[str, Any]:
"""获取所有配置"""
return self._config_dict.copy()
# 使用示例
config = ConfigManager()
# 获取配置
db_host = config.get('DB_HOST', 'localhost')
api_key = config.get('API_KEY')
# 需要时重新加载
config.reload()
配置文件 config.py 这样写:
# config.py
DB_HOST = "localhost"
DB_PORT = 5432
API_KEY = "your_api_key_here"
DEBUG = True
这样你在运行时改 config.py 里的值,调用 config.reload() 就能立刻生效。用单例确保全局只有一个配置实例,加锁避免并发问题。
简单说就是:用 importlib.reload 加热更新方法最省事。
关键是如何优雅的避免脏读呢?
配置中心服务了解一下?
正常应该是接受处理 USR1 信号,平滑重载更新配置缓存吧,你总不能开着文件句柄一直读,太难受了…
小工具用不上这个吧?
增加一个接口,被调用时从外部拉取配置更新到内存里,我的 openrestry 就是这么操作的
那你在其他地方引用该配置的时候, 是用的时候在引用吗?
还是在开头就引用了?
也就是
from conf import xxx
class X():
def xx():
XXX
还是
class X():
def xx():
from conf import xxx
XXX
赞同#4
简化来说的话就是 global config = {} , 全局变量,不过细化来说的话还涉及到读写锁
一般是 HUP 信号吧
抱歉, 我去认真看一下 USR1 和如何应用
我原帖的举例就是 gloabl conf=dict(), 不过没涉及到独写锁, 你提醒了我
openrestry 在 init-worker 阶段可以注册定时器,你这样相当于每个请求都耦合了一次配置刷新的操作
看 USR1 的应用, 以及 uwsgi 的配置文档重启, 但那个适合静态的配置, 改一次重启一次服务,
可我只想依赖这个配置的模块能获取到新的值, 并不想重启整个服务, 因为我这只是一个工具, 并不会涉及到并发之类的
可以借鉴配置中心…或者说可以把配置写在数据库里面,系统文件里面都行…
合理的事务控制,中心化配置
用 apollo
inotify 监控配置文件,有变更就调用重载配置函数
配置文件的库的库最好支持参数设置是否可以热重载
请使用 python 里最牛逼的配置文件库 oslo.cfg
看 openstack 时, 看过 oslo 的用法, 没有仔细研究过, 确实可以试试
这个有点大材小用了
熟悉以后 只要你还用 py, 这玩意可以用不少年
不 py 语言允许都可以抄一份
好! 之后也要搞 openstack, 大不了我把离线包加到依赖包里, 装我这个工具的时候, 直接装进去