使用SQLAlchemy在Python中循环导入

使用SQLAlchemy在Python中循环导入,python,sqlalchemy,Python,Sqlalchemy,我的项目: project_name |- my_app |- __init__.py |- run.py |- models.py 第一个示例 run.py from flask import Flask from flask_sqlalchemy import SQLAlchemy app = Flask(__name__) db = SQLAlchemy(app) from models import User db.create_all() if __name__ == '

我的项目:

project_name
|- my_app
   |- __init__.py
|- run.py
|- models.py
第一个示例

run.py

from flask import Flask
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)
db = SQLAlchemy(app)

from models import User
db.create_all()

if __name__ == '__main__':
    app.run()
from my_app import app

if __name__ == '__main__':
    app.run()
models.py

from run import db

class User(db.Model):
    #...
from my_app import db

class User(db.Model):
    #...
__init.py_u;为空

运行此示例后,我发现以下错误:

ImportError: cannot import name User
这个错误描述了models.py中app变量的循环导入(据我所知)

第二个示例

run.py

from flask import Flask
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)
db = SQLAlchemy(app)

from models import User
db.create_all()

if __name__ == '__main__':
    app.run()
from my_app import app

if __name__ == '__main__':
    app.run()
models.py

from run import db

class User(db.Model):
    #...
from my_app import db

class User(db.Model):
    #...
__初始化__

from flask import Flask
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)
db = SQLAlchemy(app)

from models import User
db.create_all()
现在一切都正常了

在这一点上,我不明白,为什么相同的代码给我不同的逻辑

魔法在哪里?为什么_uuuinit.py中的循环导入不会抛出错误


谢谢大家!

我只想谈谈您的第一个示例,因为您实际上可以在不更改代码的情况下复制这两个场景:

示例1:直接运行
Run.py
查看导入错误

示例2:打开python repl,然后运行:

from run import app
app.run()
您的第一个示例现在可以工作了,原因与您的第二个代码示例相同:导入已从
\uuuuu main\uuuuuu

在示例1中,
run.py
是顶级执行环境,这里的代码在
\uuuuuu main\uuuuu
中运行。对
models.py
的相对导入要求解析
models.py
中的所有引用(因为从
models.py
导入的类可能依赖于类本身之外的
models.py
的其他部分)。
models.py
做的第一件事是返回到
\uuuuu main\uuuuu
执行
db
的相对导入,因为它需要解析所有引用,所以它会解析-它尝试解析的引用之一是原始的
from models import user
语句。瞧,恐怖

问题是,此时,
run.py
尚未完成执行,到目前为止,它仍在尝试导入
User
的定义。但是现在 My.Py < /Cord>试图调用它,好像它已经完成了加载,并且它期望<>代码> Run.Py < /Cord>已经知道了<代码>用户< />代码的定义,即使它在试图找出精确的东西的中间。p> 这不是一个循环导入-不是真的
models.py
正在尝试从尚未完成执行且其内容不可用的文件导入

通过将
\uuuuuuu main\uuuuuuu
移到repl中的其他位置,或者通过移动代码使run.py不定义任何内容,可以让代码有机会在任何代码尝试使用它们之前实际解析所有依赖项。使用run import app中的
;app.run()
这是唯一未执行的代码。导入本身都可以完成它们的工作,解决它们的依赖关系,并将它们提供给
\uuuu main\uuuu


tl;当
\uuuuuuu main\uuuuu
还不知道需要什么时,dr don't意外地编写了从
\uuuuuuuu main\uuuuuuuuu
导入的代码

谢谢您的回答!如果我理解正确,我的第一个示例不起作用,因为我试图在执行的文件中使用循环导入?@jQuick这或多或少就是它的结论-需要记住的重要一点是,正在执行的文件尚未解析其所有定义,因此它还没有准备好让其他文件尝试从中导入内容。