Dockerized FastAPI SQLAlchemy PostgreSQL 'NoneType'对象没有属性'execute'

5kgi1eie  于 5个月前  发布在  PostgreSQL
关注(0)|答案(1)|浏览(79)

这是一个突然的错误,其根本原因我还没有能够弄清楚。我成功地构建了两个Docker镜像,它们通过同一个网络连接:

  1. FastAPI
  2. PostgreSQL
    我无法使用SQLAlchemy依赖注入连接到我的数据库。然而,我能够多次成功地为我的数据库播种。只向我的SQLAlchemy模型添加了一个额外的字段,然后就发生了这个失败。
backend-web-1  | ERROR:services.utils:Health check failed in 0.00 seconds: 'NoneType' object has no attribute 'execute'
backend-web-1  | ERROR:services.utils:Traceback (most recent call last):
backend-web-1  |   File "/app/main.py", line 27, in read_root
backend-web-1  |     db.execute('SELECT 1')
backend-web-1  |     ^^^^^^^^^^
backend-web-1  | AttributeError: 'NoneType' object has no attribute 'execute'

字符串
上面的代码失败发生在这里

from fastapi import FastAPI, Request, Depends, HTTPException
from sqlalchemy.orm import Session
import psutil
import threading
import time
import traceback

# Import your application modules
from database.database_config import get_db
from database.models import *
from database.crud import *
from api.interview import complete_interview
from api.chat_handling import *
from api.user_registration import register_user
from api.stripe import *
from services.utils import *
from config.env_var import *

app = FastAPI()

@app.get("/")
def read_root(db: Session = Depends(get_db)):
    
    start_time = time.time()
    try:
        # Check database connectivity
        db.execute('SELECT 1')
        db_status = "Connected"

        # Memory and Thread Count
        memory_usage = psutil.virtual_memory().percent
        thread_count = threading.active_count()

        response_time = time.time() - start_time
        logger.info(f"Health check passed in {response_time:.2f} seconds, Memory Usage: {memory_usage}%, Thread Count: {thread_count}, DB Status: {db_status}")
        return {"message": "Hello, World!"}

    except Exception as e:
        response_time = time.time() - start_time
        logger.error(f"Health check failed in {response_time:.2f} seconds: {e}")
        logger.error(traceback.format_exc())
        raise HTTPException(status_code=500, detail=str(e))


作为参考,下面是我如何定义依赖注入:

from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker

from services.utils import logger
import traceback
from config.env_var import *

DB_USER = os.getenv('DB_USER')
DB_PASSWORD = os.getenv('DB_PASSWORD')
DB_HOST = os.getenv('DB_HOST')
DB_NAME = os.getenv('DB_NAME')

Base = declarative_base()
db_url = f'postgresql://{DB_USER}:{DB_PASSWORD}@{DB_HOST}:5432/{DB_NAME}'

try:
    engine = create_engine(db_url)
except Exception as e:
    logger.info(f"Error creating database engine: {e}")
    logger.info(traceback.format_exc())
    raise

SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)

def get_db():
    db = SessionLocal()
    try:
        yield db
    except Exception as e:
        logger.info(f"Database session error: {e}")
        logger.info(traceback.format_exc())
        raise
    finally:
        db.close()


我可以通过我的FastAPI Docker示例成功连接到我的PostgreSQL示例,通过这个脚本:

from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
import os

DB_USER = os.getenv('DB_USER')
DB_PASSWORD = os.getenv('DB_PASSWORD')
DB_HOST = os.getenv('DB_HOST')
DB_NAME = os.getenv('DB_NAME')

db_url = f'postgresql://{DB_USER}:{DB_PASSWORD}@{DB_HOST}:5432/{DB_NAME}'
engine = create_engine(db_url)
SessionLocal = sessionmaker(bind=engine)

def test_session_local():
    session = SessionLocal()
    print(f"Session: {session}")
    session.close()

def test_db_connection():
    try:
        db = SessionLocal()
        # Perform a simple query
        result = db.execute('SELECT 1')
        for row in result:
            print(row)
        db.close()
        print("Connection successful.")
    except Exception as e:
        print(f"Connection failed: {e}")

if __name__ == "__main__":
    test_session_local()
    test_db_connection()


我不知道我在哪里犯了一个严重的错误。

unguejic

unguejic1#

在@MatsLindh的建议之后,我意识到错误来自 * 另一个端点 *
它的定义是:

import stripe
from datetime import datetime, timedelta
from sqlalchemy.orm import Session
from fastapi import Request, Depends, HTTPException
from typing import Callable, Dict

from config.env_var import STRIPE_WEBHOOK_SECRET
from database.crud import get_user_by_email, update_user_info
from database.enums import onboard_complete, two_chat, ten_chat, twenty_chat, monthly_subscription
from services.utils import logger

def stripe_api_client() -> stripe:
    return stripe

def get_db() -> Session:
    pass

async def extract_event(request: Request, stripe_api: stripe = Depends(stripe_api_client)):
    payload = await request.body()
    sig_header = request.headers.get('stripe-signature')
    try:
        return stripe_api.Webhook.construct_event(payload, sig_header, STRIPE_WEBHOOK_SECRET)
    except ValueError as e:
        logger.error(f"Invalid payload: {e}")
        raise HTTPException(status_code=400, detail="Invalid payload")
    except stripe.error.SignatureVerificationError as e:
        logger.error(f"Invalid signature: {e}")
        raise HTTPException(status_code=400, detail="Invalid signature")

字符串
问题出在这个部分,它实际上传递了一个None Type对象,它覆盖了我的database_config.py中的get_db

def get_db() -> Session:
    pass


所以我删除了它并导入了get_db,问题解决了!

相关问题