导入同一文件无关函数时触发KeyError问题求助
问题解决:KeyError: 'SECRET_KEY' 处理方案
错误回溯
Traceback (most recent call last): File "/Users/sergioleylanguren/Desktop/Route Decider/routelookup/app.py", line 7, in <module> from config import init_config File "/Users/sergioleylanguren/Desktop/Route Decider/routelookup/config.py", line 27, in <module> class Config: File "/Users/sergioleylanguren/Desktop/Route Decider/routelookup/config.py", line 32, in Config SECRET_KEY = values['SECRET_KEY'] ~~~~~~^^^^^^^^^^^^^^ KeyError: 'SECRET_KEY'
问题根源
Python模块导入时会执行所有顶级代码:当你从config导入init_config时,config.py的全部代码都会被运行,包括Config类的定义。此时.env文件尚未创建,dotenv_values(env_file_fp)返回空字典,直接用values['SECRET_KEY']会触发KeyError——你的init_config还没来得及生成配置文件,Config类的属性就已经加载完毕。
以下是保留init_config在config.py内的可行解决方案:
方案1:延迟配置加载到类方法
修改config.py的Config类,将配置读取逻辑封装到类方法中,避免模块导入时触发:
class Config: DEBUG = True DEVELOPMENT = True _values = None @classmethod def load_config(cls): """在init_config之后调用,加载.env配置""" cls._values = dotenv_values(env_file_fp) @property def SECRET_KEY(self): return self._values.get('SECRET_KEY', '') if self._values else '' @property def FLIGHTRADAR_USERNAME(self): return self._values.get('FLIGHTRADAR_USERNAME', '') if self._values else '' @property def FLIGHTRADAR_PASSWORD(self): return self._values.get('FLIGHTRADAR_PASSWORD', '') if self._values else '' @property def NAVIGRAPH_USERNAME(self): return self._values.get('NAVIGRAPH_USERNAME', '') if self._values else '' @property def NAVIGRAPH_PASSWORD(self): return self._values.get('NAVIGRAPH_PASSWORD', '') if self._values else ''
对应修改app.py,确保先初始化配置文件再加载Config属性:
from config import init_config, Config import atexit from pathlib import Path from flask import Flask FILE_DIR = Path(__file__).resolve().parent / "data" / "data.txt" test_config = None # 先创建.env文件 init_config() # 加载配置到Config类 Config.load_config() app = Flask(__name__) app.config.from_object(Config)
方案2:用get方法避免KeyError并重新加载
如果不想改动Config类的结构,先通过get方法设置默认值避免导入报错,再在init_config后重新读取配置:
修改config.py的Config类:
class Config: values = dotenv_values(env_file_fp) DEBUG = True DEVELOPMENT = True # 用get方法设置默认值,防止导入时触发KeyError SECRET_KEY = values.get('SECRET_KEY', '') FLIGHTRADAR_USERNAME = values.get('FLIGHTRADAR_USERNAME', '') FLIGHTRADAR_PASSWORD = values.get('FLIGHTRADAR_PASSWORD', '') NAVIGRAPH_USERNAME = values.get('NAVIGRAPH_USERNAME', '') NAVIGRAPH_PASSWORD = values.get('NAVIGRAPH_PASSWORD', '') @classmethod def reload_config(cls): """重新读取.env文件更新配置值""" cls.values = dotenv_values(env_file_fp) cls.SECRET_KEY = cls.values.get('SECRET_KEY', '') cls.FLIGHTRADAR_USERNAME = cls.values.get('FLIGHTRADAR_USERNAME', '') cls.FLIGHTRADAR_PASSWORD = cls.values.get('FLIGHTRADAR_PASSWORD', '') cls.NAVIGRAPH_USERNAME = cls.values.get('NAVIGRAPH_USERNAME', '') cls.NAVIGRAPH_PASSWORD = cls.values.get('NAVIGRAPH_PASSWORD', '')
修改app.py:
from config import init_config, Config import atexit from pathlib import Path from flask import Flask FILE_DIR = Path(__file__).resolve().parent / "data" / "data.txt" test_config = None init_config() # 重新加载最新的.env配置 Config.reload_config() app = Flask(__name__) app.config.from_object(Config)
方案3:动态生成Config类
把Config类的定义放到函数中,在init_config之后再生成类:
修改config.py:
def get_config_class(): """动态生成配置类,确保读取已存在的.env文件""" values = dotenv_values(env_file_fp) class Config: DEBUG = True DEVELOPMENT = True SECRET_KEY = values['SECRET_KEY'] FLIGHTRADAR_USERNAME = values['FLIGHTRADAR_USERNAME'] FLIGHTRADAR_PASSWORD = values['FLIGHTRADAR_PASSWORD'] NAVIGRAPH_USERNAME = values['NAVIGRAPH_USERNAME'] NAVIGRAPH_PASSWORD = values['NAVIGRAPH_PASSWORD'] return Config
修改app.py:
import config import atexit from pathlib import Path from flask import Flask FILE_DIR = Path(__file__).resolve().parent / "data" / "data.txt" test_config = None # 先创建.env文件 config.init_config() # 此时再生成Config类,确保读取到最新配置 Config = config.get_config_class() app = Flask(__name__) app.config.from_object(Config)
内容的提问来源于stack exchange,提问作者Sergio Ley
相关产品推荐
相关产品推荐

