ImportError: невозможно импортировать имя ‘app’ из частично инициализированного модуля ‘application’ (вероятно, из-за кругового импорта)

Вопрос или проблема

Я думаю, что у меня есть круговой импорт между main.py и init.py при инициализации приложения, но я не могу понять, как правильно это настроить.

Буду признателен за любую помощь. Я включил несколько изображений о проекте.

Ошибка: При импорте 'main' возникло исключение ImportError:

Трассировка (последний вызов последним):    Файл "/Users/x/Sites/learning/python/flask/venv/lib/python3.9/site-packages/flask/cli.py", строка 218, в locate_app
    __import__(module_name)   

Файл "/Users/x/Sites/learning/python/flask/main.py", строка 1, в <module> из application import app   Файл "/Users/x/Sites/learning/python/flask/application/__init__.py", строка 4, в <module>
    из application import routes   

Файл "/Users/x/Sites/learning/python/flask/application/routes.py", строка 1, в <module>
    из application import app, db 

ImportError: невозможно импортировать имя 'app' из частично инициализированного модуля 'application' **(вероятно, из-за кругового импорта)** (/Users/x/Sites/learning/python/flask/application/__init__.py)

Вот несколько скриншотов проекта:

Структура проекта

Установленные пакеты:

Установленные пакеты

main.py

из application import app

init.py

из flask import Flask
из config import Config
из flask_mongoengine import MongoEngine
из application import routes

db = MongoEngine()
app = Flask(__name__)
app.config.from_object(Config)
db.init_app(app)

routes.py

из application import app, db
из flask import render_template, request, Response, json

courseData = [
        {"courseID": "1111", "title": "PHP 111", "description": "Введение в PHP", "credits": "3", "term": "Осень, Весна"},
        {"courseID": "2222", "title": "Java 1", "description": "Введение в программирование на Java", "credits": "4","term": "Весна"},
        {"courseID": "3333", "title": "Adv PHP 201", "description": "Продвинутая программирование на PHP", "credits": "3", "term": "Осень"},
        {"courseID": "4444", "title": "Angular 1", "description": "Введение в Angular", "credits": "3","term": "Осень, Весна"},
        {"courseID": "5555", "title": "Java 2", "description": "Продвинутая программирование на Java", "credits": "4","term": "Осень"}]

@app.route("/")
@app.route("/index")
def index():
    return render_template("index.html", index=True)

@app.route("/login")
def login():
    return render_template("login.html", login=True)

@app.route("/enrollment", methods=["GET","POST"])
def enrollment():
    id = request.form.get('courseID')
    title = request.form['title']
    term = request.form.get('term')
    return render_template("enrollment.html", enrollment=True, data={"id":id,"title":title,"term":term})

@app.route("/courses")
@app.route("/courses/<term>")
def courses(term="2024"):
    return render_template("courses.html", courseData=courseData, courses=True, term=term)

@app.route("/register")
def register():
    return render_template("register.html", register=True)

@app.route("/api/")
@app.route("/api/<idx>")
def api(idx=None):
    if idx is None:
        jdata = courseData
    else:
        jdata = courseData[int(idx)]
    return Response(json.dumps(jdata), mimetype="application/json")

class User(db.Document):
    user_id = db.IntField(unique=True)
    first_name = db.StringField(max_length=50)
    last_name = db.StringField(max_length=50)
    email = db.StringField(max_length=30)
    password = db.StringField(max_length=30)

@app.route("/user")
def user():
    User(user_id=1, first_name="x", last_name="x", email="[email protected]", password="pass").save()
    User(user_id=2, first_name="Sam", last_name="x", email="[email protected]", password="pass").save()
    users = User.objects.all()
    return render_template("user.html", users=users)

Что конкретно вы сделали в routes? Проблема, вероятно, в этом.

Ответ или решение

Ошибка ImportError: cannot import name 'app' from partially initialized module 'application' (most likely due to a circular import) указывает на наличие проблемы с "циклическим импортом" в вашем коде на Python. Эта проблема часто возникает в проектах, когда два или более модуля пытаются импортировать друг друга, что создает цикл, в результате которого Python не может правильно инициализировать модули. Давайте рассмотрим, как это происходит в вашем случае, и как вы можете это исправить.

Анализ структуры проекта

Исходя из вашего описания и приведенного кода, вы имеете три основных файла в проекте:

  1. main.py
  2. application/init.py
  3. application/routes.py

В файле main.py вы импортируете app из модуля application, а в файле application/__init__.py вы также имплементируете routes, который в свою очередь пытается импортировать app снова. Это создает циклическую зависимость.

Подробный разбор

  1. Основной модуль main.py:

    from application import app
  2. Инициализация приложения в application/__init__.py:

    from flask import Flask
    from config import Config
    from application import routes
    
    db = MongoEngine()
    app = Flask(__name__)
    app.config.from_object(Config)
    db.init_app(app)
  3. Файл маршрутов application/routes.py:

    from application import app, db

Способы решения

Чтобы устранить циклический импорт, вы можете следовать нескольким шагам:

1. Измените порядок импорта

Попробуйте изменить порядок импорта в файле application/routes.py. Например, перенесите импорт app в функции, где он вам нужен, а не на уровне модуля:

# application/routes.py
from application import db
from flask import render_template, request, Response, json

def get_app():
    from application import app
    return app

@app.route("/")
@app.route("/index")
def index():
    app = get_app()
    return render_template("index.html", index=True)

# Остальные маршруты...

2. Используйте lazy loading (отложенный импорт)

Если переставить импорты не помогает, вы можете использовать так называемый lazy loading, делая импорт внутри функций или методов, что позволяет избежать циклического импорта.

3. Пересмотрите структуру проекта

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

4. Убедитесь в правильности настройки приложения

Также стоит удостовериться, что вы правильно организовали файлы конфигурации и подключения к БД, что улучшит читаемость и поддерживаемость кода.

Заключение

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

Оцените материал
Добавить комментарий

Капча загружается...