跳转到主要内容

fastapi项目结构


.
├── main.py              # 主应用文件
├── config.py            # 配置文件
├── run.py               # 启动脚本
├── requirements.txt     # 项目依赖
├── .env                 # 环境变量
├── README.md            # 项目说明
├── routers/             # 路由
├── models/              # 数据模型
├── schemas/             # 数据架构  
├── repositories/        # 数据库操作
├── services/            # 业务逻辑
└── utils/               # 工具类

公共日志类
# common_logger.py

import logging
import sys

__all__ = ["get_logger"]

# 1. 只初始化一次
_INITIALIZED = False

# 2. 颜色表 + Windows 兼容
COLORS = {
    "DEBUG": "\033[36m",
    "INFO": "\033[32m",
    "WARNING": "\033[33m",
    "ERROR": "\033[31m",
    "CRITICAL": "\033[35m",
    "RESET": "\033[0m",
}


def _init_logger(level: int = logging.INFO):
    global _INITIALIZED
    # force=True 防止重复
    if _INITIALIZED:
        return

    class ColorFormatter(logging.Formatter):
        def format(self, record):
            levelname = record.levelname
            record.levelname = (
                f"{COLORS.get(levelname, '')}{levelname}{COLORS['RESET']}"
            )
            return super().format(record)

    handler = logging.StreamHandler(sys.stdout)
    handler.setFormatter(
        ColorFormatter(
            fmt="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
            datefmt="%Y-%m-%d %H:%M:%S",
        )
    )
    logging.basicConfig(level=level, handlers=[handler], force=True)
    # force=True 防止重复
    _INITIALIZED = True


def get_logger(name: str, level: int = logging.INFO) -> logging.Logger:
    _init_logger(level)
    return logging.getLogger(name)



uvicorn 日志根式统一


#!/usr/bin/env python3
"""
FastAPI 应用启动脚本
"""

import uvicorn
from config import settings
from common_logger import get_logger

log = get_logger(__name__)

LOGGING_CONFIG = {
    "version": 1,
    "disable_existing_loggers": False,
    "formatters": {
        "default": {
            "fmt": "%(asctime)s - %(name)s - %(levelname)s - %(message)s",
        },
        "access": {
            "fmt": "%(asctime)s - %(name)s - %(levelname)s - %(message)s",
        },
    },
}


if __name__ == "__main__":
    log.info(f"启动 {settings.app_name} v{settings.app_version}")
    log.info(f"服务器地址: http://{settings.host}:{settings.port}")
    # print(f"API 文档: http://{settings.host}:{settings.port}/docs")
    log.info("-" * 50)

    uvicorn.run(
        "main:app",
        host=settings.host,
        port=settings.port,
        reload=settings.reload,
        log_level=settings.log_level.lower(),
        log_config=LOGGING_CONFIG,
    )