Flask - Не удается использовать экземпляр сельдерея в app / __ init__.py? - PullRequest
0 голосов
/ 31 января 2020

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

У нас есть приложение, основанное на Flask + Gunicorn + Nginx, которое всегда работало без серьезных проблем. Однако нам нужно построить решение, которое требует асинхронных задач. Вскоре было принято единодушное мнение, использовать для этого Celery, но даже следуя стилю, используемому здесь .

Я не могу заставить проект скомпилироваться, поскольку он сообщает об ошибках импорта, а официальная документация фреймворка не дает ясности относительно того, как его использовать в фабрике структур , как это сделать в одном случае.

Как мне решить эту проблему?

Мой след:

  File "/home/user/Workspace/test/project_async/celery_runner.py", line 3, in <module>
    from app import create_app
  File "/home/user/Workspace/test/project_async/app/__init__.py", line 9, in <module>
    from .api import configure as config_api
  File "/home/user/Workspace/test/project_async/app/api.py", line 3, in <module>
    from .resources.chosen import Change
  File "/home/user/Workspace/test/project_async/app/resources/chosen.py", line 5, in <module>
    from app.jobs.tasks import exec_change as tk_change
  File "/home/user/Workspace/test/project_async/app/jobs/tasks.py", line 1, in <module>
    from app import celery
ImportError: cannot import name 'celery' from 'app' (/home/user/Workspace/test/project_async/app/__init__.py)

Мой структура:

.
├── app
│   ├── api.py
│   ├── jobs
│   │   ├── celeryconfig.py
│   │   ├── __init__.py
│   │   └── tasks.py
│   ├── jwt.py
│   ├── models
│   │   ├── core.py
│   │   ├── __init__.py
│   │   ├── inventory.py
│   │   └── other.py
│   ├── resources
│   │   ├── chosen.py
│   │   └── __init__.py
│   ├── schemas.py
│   ├── services
│   │   ├── chosen.py
│   │   ├── base.py
│   │   ├── chosen_other.py
│   │   └── inventory.py
│   ├── static
│   │   ├── swagger.json
│   │   └── swagger.yaml
│   ├── swagger.py
│   └── utils.py
├── celery_runner.py
├── config.py
├── main.py
├── test.log
└── tests
    ├── __init__.py
    └── test_inventory.py

код:

путь - приложение / __ init __. py

from flask import Flask
from flask_cors import CORS
from flask_migrate import Migrate

from config import configure as config_project

from .api import configure as config_api
from .jwt import configure as config_jwt
from .models.core import configure as config_db
from .models.inventory import configure as config_db_mongo
from .swagger import configure as config_docs
from celery import Celery

celery = Celery(__name__)

def create_app(config_name):

    app = Flask(__name__)

    '''Added Configurations'''
    config_project(app)
    config_jwt(app)
    config_api(app)
    config_docs(app)
    config_db(app)
    config_db_mongo(app)
    '''Added Thirds'''
    CORS(app)
    Migrate(app, app.db)
    '''Background Tasks'''
    celery.conf.update(app.config)
    celery.config_from_object('app.jobs.celeryconfig')

    return app

путь - project_async / celery_worker.py

from dotenv import find_dotenv, load_dotenv

from app import create_app

load_dotenv(find_dotenv())

app = create_app(getenv('FLASK_ENV') or 'default')
app.app_context().push()

путь - app / jobs / celeryconfig.py

broker_url = 'redis://localhost:6379/1'
result_backend = 'redis://localhost:6379/0'

# import
imports = 'app.jobs.tasks'

# Timezone
timezone = 'America/Bogota'
enable_utc = True

путь - app / jobs / tasks.py

from app import celery
from app.services.chosen_other import ChangeOpportunity


@celery.task(name='tasks.change')
def exec_change(data, change, client):
    change = ChangeOpportunity(data, change, client)
    change.execute_change()

1 Ответ

0 голосов
/ 02 февраля 2020

Это вызвано круговым импортом. Фактическая проблема заключается в том, что импорт api.py заканчивается импортом ваших задач Celery. Так как вы делаете from .api import configure перед тем, как определить экземпляр celery, это нарушается круговой зависимостью.

Вы должны попытаться реорганизовать свой код так, чтобы импорт одного модуля не требовал много других модулей для импорта. Если вы посмотрите на трассировку стека, вы увидите, что api.py импортирует resources/chosen.py, что импортирует jobs/tasks.py. Необходим ли весь кросс-пакетный импорт?

Попробуйте разбить более сложные модули, чтобы у вас не было всех этих косвенных импортов.

...