Flask应用导入mail报错ImportError问题求助
Flask邮件发送导入失败问题解决
项目结构
└── my-project │ ├── __init__.py ├── app.py │ ├── api │ ├── __init__.py │ ├── list.py │ └── routes.py │ └── mail ├── __init__.py └── email.py
所有__init__.py文件均为空。
问题重现
在api/list.py中调用sendemail()函数:
<other imports> from mail.email import sendemail class FeedApi(Resource): def get(self, start: int, limit: int) -> Response: output = Lists.objects().aggregate( <... query stuff ...> lists = json.loads(json_util.dumps(output)) sendemail() return lists
email.py初始代码可正常运行:
from flask_mail import Message def sendemail(): print('\n\n trying to import this function ')
但修改email.py为以下代码时,触发ImportError: cannot import name 'mail' from 'app':
from flask_mail import Message def sendemail(): from app import mail print('\n\n trying to import this function ')
若将from app import mail放在函数外,会触发循环导入错误。
问题原因
查看app.py代码可知,mail是在get_flask_app函数内部定义的局部变量,并未暴露在app模块的全局作用域中,因此无法通过from app import mail导入。
解决方案
方案1:将mail提升为模块全局变量
修改app.py,把mail的定义移到函数外,在函数内完成初始化:
# flask packages from flask import Flask, current_app, request, app from flask_cors import CORS from flask_restful import Api from flask_mongoengine import MongoEngine from flask_jwt_extended import JWTManager from flask_cors import CORS from flask_mail import Mail # 全局声明mail变量 mail = None # local packages from api.routes import create_routes # external packages import os # default mongodb configuration default_config = {'MONGODB_SETTINGS': { 'db': '.... ', 'host': '....', 'port': 27017, 'username': '...', 'password': '...', 'authentication_source': '...'}, 'JWT_SECRET_KEY': '...'} def get_flask_app(config: dict = None) -> app.Flask: global mail # 声明使用全局变量 # init flask Flask.logger_name = "listlogger" flask_app = Flask(__name__) CORS(flask_app) # configure app flask_app.config.from_pyfile('config.py') config = default_config if config is None else config flask_app.config.update(config) # load config variables if 'MONGODB_URI' in os.environ: flask_app.config['MONGODB_SETTINGS'] = {'host': os.environ['MONGODB_URI'], 'retryWrites': False} if 'JWT_SECRET_KEY' in os.environ: flask_app.config['JWT_SECRET_KEY'] = os.environ['JWT_SECRET_KEY'] mail = Mail(app=flask_app) # 初始化全局mail实例 # init api and routes api = Api(app=flask_app) create_routes(api=api) # init mongoengine db = MongoEngine(app=flask_app) # init jwt manager jwt = JWTManager(app=flask_app) return flask_app if __name__ == '__main__': # Main entry point when run in stand-alone mode. app = get_flask_app() app.run(debug=True, host='0.0.0.0', port=5050)
之后在email.py中即可在函数内安全导入:
from flask_mail import Message def sendemail(): from app import mail # 这里可以添加邮件发送逻辑,例如: # msg = Message('测试邮件', sender='your@email.com', recipients=['target@email.com']) # msg.body = '这是一封测试邮件' # mail.send(msg) print('\n\n trying to import this function ')
方案2:使用Flask current_app获取mail实例
无需修改app.py,直接通过current_app.extensions获取已初始化的mail实例,更符合Flask应用工厂模式的最佳实践:
from flask import current_app from flask_mail import Message def sendemail(): mail = current_app.extensions['mail'] # 后续添加邮件发送逻辑 print('\n\n trying to import this function ')
验证
修改完成后,启动Flask应用,触发FeedApi的GET请求,确认sendemail()函数可正常执行且无导入错误。
内容的提问来源于stack exchange,提问作者planetstarbucks
相关产品推荐
相关产品推荐

