我有一个烧瓶应用程序,其根文件夹名为project_folder
。
这个project_folder
包的__init__.py
文件的代码片段:
@jwt.token_in_blacklist_loader
def check_if_token_in_blacklist(decrypted_token):
jti = decrypted_token['jti']
return project_folder.Model.RevokedTokenModel.is_jti_blacklisted(jti)
from project_folder.Controller.root import root
from project_folder.Controller import auth_controller
from project_folder.Controller import item_controller
现在有趣的是,project_folder
包本身自然有其他较小的包,我正在导入这些包以使用它们(在本例中用于REST资源(。这是最后3行,到目前为止没有出现任何错误。
但是,如果您查看带注释的函数(在本例中,它总是在使用某种JWT令牌之前运行(,我将返回一些内部包的函数。现在,当逻辑真正运行这一部分时,代码就会中断:
PROJECT_ROUTEproject_folder__init__.py", line 38, in check_if_token_in_blacklist
return project_folder.Model.RevokedTokenModel.is_jti_blacklisted(jti)
NameError: name 'project_folder' is not defined
经过思考,这似乎是可以理解的。从project_folder
导入确实从包的__init__.py
文件导入,这是解释器当前的实际文件。因此,从中删除包名称前缀
return project_folder.Model.RevokedTokenModel.is_jti_blacklisted(jti)
至
return Model.RevokedTokenModel.is_jti_blacklisted(jti)
不再抛出错误。
问题是:为什么这只是回调函数内部的问题,而不是最后3个导入的问题?
这与python中的循环导入有关。循环导入是一种循环依赖关系,在模块导入级别创建。
工作原理:
当您启动应用程序时,python会保留一个寄存器(一种表(,在其中记录所有导入的模块。当你在代码中的某个地方调用一个模块时,python会在它的注册表中看到它是否已经注册并从那里加载它。您可以通过sys.module
访问此注册表,它实际上是一个dictionary
,包含自Python启动以来导入的所有模块。
使用示例:
>>> import sys
>>> print('n'.join(sys.modules.keys()))
因此,由于Python是一种解释语言,代码的读取和执行是从上到下逐行完成的。
在您的代码中,您将导入放在__init__.py
文件的底部。
在浏览它时,当python到达return project_folder.Model.RevokedTokenModel.is_jti_blacklisted(jti)
行时,它将查看该模块是否存在于其寄存器中。现在显然还不是这样。这就是他提出NameError: name 'project_folder' is not defined
异常的原因。