包裹 'see' 本身在 __init__.py 中吗?
Does a package 'see' itself in __init__.py?
我有一个 flask 应用程序,其根文件夹名为 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_ROUTE\project_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 会保留一个寄存器(一种 table),其中记录了所有导入的模块。当您在代码中的某处调用模块时,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
异常的原因。
我有一个 flask 应用程序,其根文件夹名为 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_ROUTE\project_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 会保留一个寄存器(一种 table),其中记录了所有导入的模块。当您在代码中的某处调用模块时,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
异常的原因。