Flask Blueprint AttributeError: объект 'module' не имеет атрибута 'name' error

Мой API создается, чтобы позволить разработчикам расширять его функциональность. Мой план состоит в том, чтобы сделать это, предоставив каталог "расширений", где они могут попасть в "Чертежи", и они будут динамически загружаться. Это код, который я использую для импорта (измененный из этого учебника)

from flask import Flask

import pkgutil
import sys

app = Flask(__name__)

EXTENSIONS_DIR = "extensions"
modules = pkgutil.iter_modules(path=[EXTENSIONS_DIR])
for loader, mod_name, ispkg in modules: 
    if mod_name not in sys.modules:
        # It imports fine
        loaded_mod = __import__(EXTENSIONS_DIR+"."+mod_name+"."+mod_name, fromlist=[mod_name])
        # It does not register
        app.register_blueprint(loaded_mod)

Это макет каталога моего проекта. Каталог extensions - это место, где разработчики расширяют свои функциональные возможности.

/root
    /extensions
        /extension1
            __init__.py
            extension1.py
        /extension2
            __init__.py
            extension2.py
    simple_example.py

Проблема в том, что я получаю эту ошибку и не уверен, что она мне говорит.

>python simple_example.py
Traceback (most recent call last):
  File "simple_example.py", line 14, in <module>
    app.register_blueprint(loaded_mod)
  File "C:\Python27\lib\site-packages\flask\app.py", line 62, in wrapper_func
    return f(self, *args, **kwargs)
  File "C:\Python27\lib\site-packages\flask\app.py", line 880, in register_blueprint
    if blueprint.name in self.blueprints:
AttributeError: 'module' object has no attribute 'name'

Простое расширение выглядит так:

from flask import Blueprint

extension1 = Blueprint('extension1', __name__)

@extension1.route("/my_route")
def treasure_list():
    return "list of objects"

Как разрешить AttributeError таким образом, чтобы мой вызов app.register_blueprint преуспеть?

Ответ 1

Вы пытаетесь зарегистрировать модуль, а не содержащий объект Blueprint.

Вам нужно будет изучить модуль, чтобы найти экземпляры Blueprint:

if mod_name not in sys.modules:
    loaded_mod = __import__(EXTENSIONS_DIR+"."+mod_name+"."+mod_name, fromlist=[mod_name])
    for obj in vars(loaded_mod).values():
        if isinstance(obj, Blueprint):
            app.register_blueprint(obj)

Ответ 2

Когда я получил эту ошибку, мой код выглядел так:

from blueprints import api
...
app.register_blueprint(api)

Я исправил это, выполнив это:

app.register_blueprint(api.blueprint)

Ответ 3

Я также испытал такой же эффект в проекте. Причиной проблемы был неправильный импорт файла чертежа.

Убедитесь, что оператор import импортирует реальный проект, а не модуль, в котором он определен.

Другими словами, вы можете делать

from .blueprint import blueprint

пока ты имел ввиду

from .blueprint.blueprint import blueprint

В качестве дополнительной рекомендации назовите модуль, для которого задан проект, имя которого отличается от самого проекта, чтобы уточнить импорт. Пример:

from .blueprint.views import blueprint