From bf9701365f2d68e8c1fdaf083139e58cc8f27118 Mon Sep 17 00:00:00 2001 From: AL76 <735756072@qq.com> Date: Tue, 11 Mar 2025 02:46:13 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E7=B2=BE=E7=AE=80=E6=97=A5=E5=BF=97?= =?UTF-8?q?=EF=BC=8C=E7=A6=81=E7=94=A8Uvicorn/NoneBot=E9=BB=98=E8=AE=A4?= =?UTF-8?q?=E6=97=A5=E5=BF=97=EF=BC=9B=E5=90=AF=E5=8A=A8=E6=96=B9=E5=BC=8F?= =?UTF-8?q?=E6=94=B9=E4=B8=BA=E6=98=BE=E7=A4=BA=E5=8A=A0=E8=BD=BDuvicorn?= =?UTF-8?q?=EF=BC=8C=E4=BB=A5=E4=BE=BF=E4=BC=98=E9=9B=85shutdown?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bot.py | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 62 insertions(+), 3 deletions(-) diff --git a/bot.py b/bot.py index c2ed3dfdf..471a98eaf 100644 --- a/bot.py +++ b/bot.py @@ -1,9 +1,12 @@ +import asyncio import os import shutil import sys import nonebot import time + +import uvicorn from dotenv import load_dotenv from loguru import logger from nonebot.adapters.onebot.v11 import Adapter @@ -12,6 +15,8 @@ import platform # 获取没有加载env时的环境变量 env_mask = {key: os.getenv(key) for key in os.environ} +uvicorn_server = None + def easter_egg(): # 彩蛋 @@ -100,10 +105,12 @@ def load_logger(): "#777777>| {name:.<8}:{function:.<8}:{line: >4} - {message}", colorize=True, - level=os.getenv("LOG_LEVEL", "DEBUG") # 根据环境设置日志级别,默认为INFO + level=os.getenv("LOG_LEVEL", "INFO"), # 根据环境设置日志级别,默认为INFO + filter=lambda record: "nonebot" not in record["name"] ) + def scan_provider(env_config: dict): provider = {} @@ -138,7 +145,39 @@ def scan_provider(env_config: dict): raise ValueError(f"请检查 '{provider_name}' 提供商配置是否丢失 BASE_URL 或 KEY 环境变量") -if __name__ == "__main__": +async def graceful_shutdown(): + try: + global uvicorn_server + if uvicorn_server: + uvicorn_server.force_exit = True # 强制退出 + await uvicorn_server.shutdown() + + tasks = [t for t in asyncio.all_tasks() if t is not asyncio.current_task()] + for task in tasks: + task.cancel() + await asyncio.gather(*tasks, return_exceptions=True) + + except Exception as e: + logger.error(f"麦麦关闭失败: {e}") + + +async def uvicorn_main(): + global uvicorn_server + config = uvicorn.Config( + app="__main__:app", + host=os.getenv("HOST", "127.0.0.1"), + port=int(os.getenv("PORT", 8080)), + reload=os.getenv("ENVIRONMENT") == "dev", + timeout_graceful_shutdown=5, + log_config=None, + access_log=False + ) + server = uvicorn.Server(config) + uvicorn_server = server + await server.serve() + + +def raw_main(): # 利用 TZ 环境变量设定程序工作的时区 # 仅保证行为一致,不依赖 localtime(),实际对生产环境几乎没有作用 if platform.system().lower() != 'windows': @@ -165,10 +204,30 @@ if __name__ == "__main__": nonebot.init(**base_config, **env_config) # 注册适配器 + global driver driver = nonebot.get_driver() driver.register_adapter(Adapter) # 加载插件 nonebot.load_plugins("src/plugins") - nonebot.run() + +if __name__ == "__main__": + + try: + raw_main() + + global app + app = nonebot.get_asgi() + + loop = asyncio.new_event_loop() + asyncio.set_event_loop(loop) + loop.run_until_complete(uvicorn_main()) + except KeyboardInterrupt: + logger.warning("麦麦会努力做的更好的!正在停止中......") + except Exception as e: + logger.error(f"主程序异常: {e}") + finally: + loop.run_until_complete(graceful_shutdown()) + loop.close() + logger.info("进程终止完毕,麦麦开始休眠......下次再见哦!")