ImportError: cannot import name ‘db‘ from partially initialized module ‘project‘
当两个模块尝试同时导入彼此以使它们相互依赖时,通常会发生循环依赖。假设我们有几个模块:demo1.py 和 demo2.py。内容如下:可以看到这两个模块是相互依赖的。在这种情况下,当我们使用像和这样的语句时,就会出现循环依赖。
解决思路和方法
一、 报错信息
ImportError: cannot import name 'db' from partially initialized module 'project' (most likely due to a circular import) (D:\projects\zfx_py\flask24\project\__init__.py)
编写完代码以后,运行falsk异常,控制台完整的信息为:
ImportError:无法从部分初始化的模块“project”导入名称“db”(很可能是由于循环导入),这种问题常出现在导入蓝图的时候,我们先来看看为啥会出现这类问题
二、python中ImportError: cannot import name 错误的原因
如果代码中的 import 语句在成功导入模块时遇到困难,则会出现 Python 中的 ImportError异常。
出现此类问题的原因通常是外部库安装错误或您尝试导入的模块路径无效。
当尝试导入的类处于循环依赖关系中时,通常会发生这种导入错误(也就是报错中most likely due to a circular import
)。
2.1、 什么是循环依赖
当两个模块尝试同时导入彼此以使它们相互依赖时,通常会发生循环依赖。
假设我们有几个模块:demo1.py 和 demo2.py。内容如下:
可以看到这两个模块是相互依赖的。在这种情况下,当我们使用像 from demo1 import demo1_func1
和 from demo2 import demo2_func2
这样的语句时,就会出现循环依赖。
三、修复Python中的 ImportError: cannot import name 错误
避免循环依赖,Python 可以自己完成。
必须修改 import 语句,而不是导入模块的内容,而是导入两个文件中的整个模块。
demo1.py源码如下:
import demo2
def demo1_func1():
print('demo1_func1')
demo2.demo2_func2()
import demo1
def demo2_func1():
print('demo2_func1')
demo1.demo1_func1()
def demo2_func2():
print('demo2_func2')
if __name__=='__main__':
demo2_func1()
执行结果如下:
四、解决方法一:根据前两步分析,找到项目中falsk运行报错的位置
报错提示是导入db循环了,这种情况又常出现在蓝图的使用中,正好先看我的蓝图,下面是我的源码,可以看到我是先导入了蓝图,才生成了db;
那来看看我的蓝图中真如前面说的,导入了db?在源码里看到我导入了models,那极大可能就是models中用到了db。
来看看modes中的源码:
还真是哈,真相了家人们。那这种很好调整哈,我们只要先创建db,再导入那些用到db的模块就可以了,如下图所示:
就正常喽
五、解决方法二:将实例化db对象处理成扩展
Flask:扩展开发的文档
扩展是为FlaskTM应用程序添加功能的额外程序包。根据文档可知:扩展实例独立于应用程序而存在。用户在项目中的其他模块可以通过from project import hello
在应用程序存在之前,在蓝图中使用该扩展。
那么在我项目的根目录下,新建一个extension.py
文件,在这里实例化SQLAlchemy。
from flask_sqlalchemy import SQLAlchemy
from flask_cors import CORS
db = SQLAlchemy()
cors = CORS()
然后,在项目任何位置,调用就可以,如下所示:
import os
from flask import Flask
from project.extension import db, cors
from project.config import config # 导入存储配置的字典
from project.blog import blog_base_blueprint
def create_app(config_name=None):
if config_name is None:
config_name = os.getenv('FLASK_ENV', 'development') # 从环境变量中获取FLASK_ENV,并设置默认值
app = Flask('project')
# setup config,导入配置,根据配置环境实例化
app.config.from_object(config[config_name])
# 注册扩展
register_extension(app)
# 注册蓝图
register_blueprint(app)
return app
# 注册flask拓展
def register_extension(app: Flask):
db.init_app(app)
db.app = app
cors.init_app(app, origins="*")
# 注册蓝图
def register_blueprint(app: Flask):
app.register_blueprint(blog_base_blueprint)
除此处修改以外,因为我还注册了蓝图,蓝图里有使用到模型,所以模型里导入db的方式也要改变一下,如下所示:
六、写在最后
宣传一波:大家若是有人想北京租房可以联系我,主要是物资学院、通州北关、北苑、草房的房子。(注:我不是中介哟,我也不打算转行做中介)
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)