main.py 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. # -*- coding: utf-8 -*-
  2. import os
  3. import sys
  4. from pathlib import Path
  5. from typing import Annotated
  6. import uvicorn
  7. import typer
  8. from fastapi import FastAPI
  9. from alembic import command
  10. from alembic.config import Config
  11. import importlib
  12. from app.common.enums import EnvironmentEnum
  13. fastapiadmin_cli = typer.Typer()
  14. # 初始化 Alembic 配置
  15. alembic_cfg = Config("alembic.ini")
  16. def create_app() -> FastAPI:
  17. """创建 FastAPI 应用实例"""
  18. from app.plugin.init_app import (
  19. register_middlewares,
  20. register_exceptions,
  21. register_routers,
  22. register_files,
  23. reset_api_docs,
  24. lifespan
  25. )
  26. from app.config.setting import settings
  27. # 创建FastAPI应用
  28. app = FastAPI(**settings.FASTAPI_CONFIG, lifespan=lifespan)
  29. from app.core.logger import setup_logging
  30. # 初始化日志
  31. setup_logging()
  32. # 注册各种组件
  33. register_exceptions(app)
  34. # 注册中间件
  35. register_middlewares(app)
  36. # 注册路由
  37. register_routers(app)
  38. # 注册静态文件
  39. register_files(app)
  40. # 重设API文档
  41. reset_api_docs(app)
  42. return app
  43. # typer.Option是非必填;typer.Argument是必填
  44. @fastapiadmin_cli.command(name="run",
  45. help="启动 FastapiAdmin 服务, 运行 python main.py run --env=dev 不加参数默认 dev 环境")
  46. def run(env: Annotated[
  47. EnvironmentEnum, typer.Option("--env", help="运行环境 (dev, prod)")] = EnvironmentEnum.DEV) -> None:
  48. """启动FastAPI服务"""
  49. try:
  50. # 设置环境变量
  51. os.environ["ENVIRONMENT"] = env.value
  52. typer.echo("项目启动中...")
  53. # 清除配置缓存,确保重新加载配置
  54. from app.config.setting import get_settings
  55. get_settings.cache_clear()
  56. settings = get_settings()
  57. from app.core.logger import setup_logging
  58. setup_logging()
  59. # 显示启动横幅
  60. from app.utils.banner import worship
  61. worship(env.value)
  62. # 检测是否为PyInstaller打包环境
  63. is_packaged = getattr(sys, 'frozen', False)
  64. if is_packaged:
  65. app = create_app()
  66. uvicorn.run(
  67. app=app,
  68. host=settings.SERVER_HOST,
  69. port=settings.SERVER_PORT,
  70. reload=False, # 打包后强制关闭 reload
  71. factory=False,
  72. log_config=None
  73. )
  74. else:
  75. app_str = "main:create_app"
  76. uvicorn.run(
  77. app=app_str, # 开发环境传字符串路径
  78. host=settings.SERVER_HOST,
  79. port=settings.SERVER_PORT,
  80. reload=env == EnvironmentEnum.DEV, # 开发环境开启 reload
  81. factory=(app_str.endswith("create_app")), # 若传函数名则开启 factory
  82. log_config=None
  83. )
  84. except KeyboardInterrupt:
  85. from app.utils.console import display_shutdown_info
  86. display_shutdown_info()
  87. except Exception as e:
  88. raise
  89. finally:
  90. from app.core.logger import cleanup_logging
  91. cleanup_logging()
  92. @fastapiadmin_cli.command(name="revision", help="生成新的 Alembic 迁移脚本, 运行 python main.py revision --env=dev")
  93. def revision(env: Annotated[EnvironmentEnum, typer.Option("--env", help="运行环境 (dev, prod)")] = EnvironmentEnum.DEV) -> None:
  94. """生成新的 Alembic 迁移脚本"""
  95. os.environ["ENVIRONMENT"] = env.value
  96. command.revision(alembic_cfg, autogenerate=True, message="迁移脚本")
  97. typer.echo(f"迁移脚本已生成")
  98. @fastapiadmin_cli.command(name="upgrade", help="应用最新的 Alembic 迁移, 运行 python main.py upgrade --env=dev")
  99. def upgrade(env: Annotated[EnvironmentEnum, typer.Option("--env", help="运行环境 (dev, prod)")] = EnvironmentEnum.DEV) -> None:
  100. """应用最新的 Alembic 迁移"""
  101. os.environ["ENVIRONMENT"] = env.value
  102. command.upgrade(alembic_cfg, "head")
  103. typer.echo("所有迁移已应用。")
  104. if __name__ == '__main__':
  105. fastapiadmin_cli()