Пакет «видит» себя в __init__.py? - PullRequest
1 голос
/ 31 октября 2019

У меня есть приложение фляги с корневой папкой с именем 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

ТеперьИнтересно, что пакет 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 импортами?

1 Ответ

1 голос
/ 31 октября 2019

Это связано с циклическим импортом в 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.

...