包是否在__init__.py中“看到”自身?

时间:2019-10-31 17:18:42

标签: python python-import nameerror python-packaging

我有一个烧瓶应用程序,其根文件夹名为::

project_folder软件包的__init__.py文件中的代码段:

project_folder

现在有趣的是,@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 包本身自然具有其他较小的包,我将其导入以使用它们(在此示例中为REST资源使用)。这是最后三行,到目前为止没有任何错误。

但是,如果您看一下带注释的函数(在此示例中,该函数始终在使用某种JWT Token之前运行),那么我将返回某些内部包的函数。现在,当逻辑真正运行此部分时,代码将中断:

project_folder

考虑之后,这似乎是可以理解的。从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)

不再抛出错误。

问题是:为什么这只是回调函数内部的一个问题,而不是最后3个导入的问题?

1 个答案:

答案 0 :(得分:1)

这与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异常。