这是第一个标题
12222222222222222222222222232132132132132132132131232132321
321323213123范德萨发
3123333333333323213213
# -*- coding: utf-8 -*-
"""
Flask应用初始化
"""
import atexit
import logging
import os
import signal
import threading
import dotenv
from flask import Flask
dotenv.load_dotenv()
# 导入全局db实例
from models import db
# 注册蓝图
from routes import main_bp, tasks_bp, novels_bp, statistics_bp, health_bp
from routes.chapters import chapter_tasks_bp
from routes.spider import spider_api_bp
from routes.media import media_bp
from utils.task_scheduler import task_scheduler
from tasks.registration import register_all_tasks
from tasks.cron_jobs import setup_cron_jobs
from utils.logger_config import setup_logging
def cleanup_on_exit():
"""应用退出时的清理函数"""
try:
# 关闭任务调度器
if task_scheduler.scheduler.running:
logger = logging.getLogger(__name__)
logger.info("正在关闭任务调度器...")
task_scheduler.shutdown(wait=True)
logger.info("任务调度器已安全关闭")
except Exception as e:
logger = logging.getLogger(__name__)
logger.exception(f"关闭任务调度器时出错: {str(e)}")
def signal_handler(signum, frame):
"""信号处理器"""
logger = logging.getLogger(__name__)
logger.info(f"接收到信号 {signum},开始优雅关闭...")
cleanup_on_exit()
os._exit(0)
def create_app(config_name='development'):
"""应用工厂函数"""
app = Flask(__name__)
# 导入配置
from config import config
# 使用项目专用的日志配置
log_level = getattr(config, 'log_level', 'DEBUG') # 开发环境默认DEBUG级别,启用HTTP请求日志
# 将日志文件放在项目根目录下的 logs 文件夹中,更容易找到
project_root = os.path.dirname(os.path.abspath(__file__))
logs_dir = os.path.join(project_root, 'logs')
os.makedirs(logs_dir, exist_ok=True)
log_file = os.path.join(logs_dir, 'tweet_engine.log')
# 使用自定义的日志配置(包含urllib3日志抑制)
setup_logging(level=log_level, log_file=log_file)
# 获取应用日志器
logger = logging.getLogger(__name__)
# 配置
app.config['SECRET_KEY'] = os.getenv('SECRET_KEY', 'dev-secret-key')
# MySQL数据库配置
database_uri = config.database_url
app.config['SQLALCHEMY_DATABASE_URI'] = database_uri
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
# 数据库连接信息
# 导入配置
from config import MONGO_URI, MONGO_DB_NAME, MONGO_COLLECTION_NAME, REDIS_URL
# MongoDB配置
app.config['MONGO_URI'] = MONGO_URI
app.config['MONGO_DB_NAME'] = MONGO_DB_NAME
app.config['MONGO_COLLECTION'] = MONGO_COLLECTION_NAME
# Redis配置(用于缓存)
app.config['REDIS_URL'] = REDIS_URL
# 初始化数据库
db.init_app(app)
# 注册Web页面blueprints
app.register_blueprint(main_bp)
app.register_blueprint(tasks_bp, url_prefix='/tasks')
app.register_blueprint(novels_bp, url_prefix='/novels')
app.register_blueprint(statistics_bp, url_prefix='/statistics')
app.register_blueprint(health_bp, url_prefix='/health')
# 注册API blueprints(这些blueprints同时包含Web页面和API端点)
app.register_blueprint(chapter_tasks_bp) # 章节任务路由
app.register_blueprint(spider_api_bp, url_prefix='/spider') # 爬虫路由
app.register_blueprint(media_bp, url_prefix='/static') # 媒体文件路由
# 创建数据库表(处理连接失败的情况)
try:
with app.app_context():
db.create_all()
# 初始化任务调度器
if not task_scheduler.scheduler.running:
# 设置Flask应用引用到task_scheduler
task_scheduler.set_app(app)
register_all_tasks()
task_scheduler.start()
# 设置定时任务
setup_cron_jobs(task_scheduler)
except Exception as e:
error_msg = str(e)
logger = logging.getLogger(__name__)
logger.exception("数据库连接失败: " + error_msg)
logger.exception("应用将在无数据库模式下运行,部分功能可能受限")
# 注册退出清理函数(只在主线程中注册)
if threading.current_thread() is threading.main_thread():
try:
# 注册atexit清理函数
atexit.register(cleanup_on_exit)
# 注册信号处理器(用于优雅关闭)
signal.signal(signal.SIGTERM, signal_handler)
signal.signal(signal.SIGINT, signal_handler)
logger.info("已注册应用退出清理函数")
except (ValueError, RuntimeError) as e:
logger.warning(f"无法注册信号处理器: {str(e)}")
return app
3213213213213213213
321321321321321321312313213
1233333333333333333333333
3213213
3213
21312
321
3213213
3213
21312
321
1 2
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END

暂无评论内容