Модуль 'a' не имеет атрибута 'b' при импорте модуля из того же каталога - PullRequest
0 голосов
/ 28 июня 2018

У меня есть следующая структура каталогов в моем проекте Python:

    - dump_specs.py
    /impa
        - __init__.py
        - server.py
        - tasks.py

У меня была проблема с циклическими ссылками. dump_specs.py нужна ссылка на app из server.py. server.py - это приложение Flask, для которого нужны ссылки на задачи из сельдерея из tasks.py. Так dump_specs.py выглядит так:

#!/usr/bin/env python3

import impa.server

def dump_to_dir(dir_path):
    # Do something
    client = impa.server.app.test_client()
    # Do the rest of things

impa/server.py выглядит так:

#!/usr/bin/env python3

import impa.tasks

app = Flask(__name__)

# Definitions of endpoints, some of them use celery tasks -
# that's why I need impa.tasks reference

И impa/tasks.py:

#!/usr/bin/env python3

from celery import Celery

import impa.server

def make_celery(app):
    celery = Celery(app.import_name,
                broker=app.config['CELERY_BROKER_URL'],
                backend=app.config['CELERY_RESULT_BACKEND'])
    TaskBase = celery.Task

    class ContextTask(TaskBase):
        abstract = True

        def __call__(self, *args, **kwargs):
            with app.app_context():
                return TaskBase.__call__(self, *args, **kwargs)

    celery.Task = ContextTask
    return celery

celery = make_celery(impa.server.app)

Когда я пытаюсь сбросить спецификации с ./dump_specs.py, у меня появляется ошибка:

./dump_specs.py specs
Traceback (most recent call last):
  File "./dump_specs.py", line 9, in <module>
    import impa.server
  File "/build/impa/server.py", line 23, in <module>
    import impa.tasks
  File "/build/impa/tasks.py", line 81, in <module>
    celery = make_celery(impa.server.app)
    AttributeError: module 'impa' has no attribute 'server'

И я не могу понять, что не так. Может кто-нибудь объяснить, что происходит и как избавиться от этой ошибки?

1 Ответ

0 голосов
/ 30 июня 2018

Если мне удалось правильно воспроизвести вашу проблему на моем хосте, это должно помочь вам вставить import impa.tasks в dump_specs.py выше import impa.server.

То, как ваши модули зависят друг от друга, важен порядок загрузки. IIRC (механизм загрузки более подробно описан в документации), когда вы впервые попытаетесь импортировать impa.server, он в строке 23 попытается импортировать impa.tasks, но импорт impa.server на этом этапе не завершен. В impa.tasks есть import impa.server, но мы не возвращаемся и не импортируем его в это время (в противном случае мы оказались бы в круге) и продолжаем импортировать impa.tasts, пока не захотим получить доступ к impa.server.app, но мы еще не дошли до того, что могли бы сделать это, impa.server еще не импортирован.

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

...