Flask Restful Web 框架专栏更新
本次示例,在上一个示例基础上,新增了定时任务模块
项目启动、部署等基础功能不再赘述,如有需要,请参考专栏第一篇的文章:
Flask Restful Web基础框架简单示例一(Mysql、Redis)_阿速之吉的博客-CSDN博客
写在前面
在实际开发项目,有的项目,需要定期处理一些任务,比如定期发送邮件、定期将mysql数据同步到Redis、定期做数据采集等。以往的作法可能是写一些独立于项目的脚本,虽然这种方法也可以实现,但是脚本相对比较零散,不易于管理。那么我给出的解决方案就是在项目中引入任务调度功能。也就是当项目启动时,定时任务模块也随之启动。这里我用到的是Python的APScheduler库。
APScheduler(Advanced Python Scheduler)是一个强大的Python库,用于在指定的时间间隔或特定时间点执行任务。它在项目组中有许多实际应用场景。
简单示例
先举一个简单的例子,让你明白APScheduler如何做到定时任务。
示例:定期打印今天的时间
使用Python的datetime模块来获取今天的日期,并且结合APScheduler来定期打印出来。
安装APScheduler模块:
pip install apscheduler
然后,创建一个Python脚本来定期打印今天的日期:
下面是一个示例代码:
from apscheduler.schedulers.background import BackgroundScheduler
from datetime import datetime
# 创建一个后台调度器
scheduler = BackgroundScheduler()
# 定义定时任务函数
def print_today_date():
today = datetime.now().date()
print(f"今天的日期是:{today}")
# 添加定时任务,每天中午12点执行一次
scheduler.add_job(print_today_date, 'cron', hour=12)
# 启动调度器
scheduler.start()
try:
# 保持主线程运行,直到手动停止脚本
while True:
pass
except (KeyboardInterrupt, SystemExit):
# 在收到中断信号或系统退出时,关闭调度器
scheduler.shutdown()
在这个示例中,我们使用APScheduler创建了一个定时任务,该任务每天中午12点执行一次 print_today_date()
函数,该函数会获取今天的日期并打印出来。
flask中使用
在已有的flask框架如何引入此模块呢?分享我的做法
先看看文件结构
启动说明
1、新建一个目录scheduler,与app同级,里面有__init__.py和tasks.py文件;__init__.py是初始化文件,里面可以是空的,tasks.py里面是具体的任务逻辑
2、在项目启动时引用
即在manage.py中导入scheduler,这样就可以在项目启动时初始化并开启定时任务了。
重点讲解
这里重点说明一个使用技巧,就是定时任务的逻辑如何去调用app里写好的数据库逻辑(查数据、写数据等),如果直接引用app中的包肯定会报关于app上下文的错。解决办法是在scheduler/tasks.py文件中创建上下文。
这里创建了一个Flask应用上下文,通过app.app_context().push()
来激活这个上下文。这是因为在Flask应用中执行定时任务时,需要确保在正确的应用上下文中运行,以便能够访问应用程序的配置、数据库和其他上下文相关的资源。
具体解释为什么需要创建上下文:
-
数据库连接和会话管理:在你的定时任务中,你可能需要访问数据库,执行查询或操作。Flask的数据库扩展通常需要在应用上下文中进行初始化,因此必须确保在数据库操作之前创建正确的上下文,以便能够连接到数据库并执行操作。
-
应用配置:应用程序的配置信息通常存储在应用上下文中。这包括数据库连接信息、密钥、调试模式等。如果你的定时任务依赖于这些配置信息,那么你需要在正确的上下文中运行以访问这些配置。
-
其他上下文相关资源:除了数据库和配置之外,还可能有其他与应用程序相关的资源需要在应用上下文中初始化和管理。这可能包括缓存、消息队列、日志记录等。
通过使用app.app_context().push()
,你可以确保在执行定时任务时,处于正确的应用上下文中,以便能够访问应用程序的所有资源和配置。这是保证定时任务能够正常运行的关键。
代码示例
scheduler/tasks.py
from app import create_app # 导入创建应用的函数
from apscheduler.schedulers.background import BackgroundScheduler
from app.models import *
from app.entities.get_tb_data import *
# 创建应用上下文
app = create_app()
app.app_context().push()
# 创建一个后台调度器
scheduler = BackgroundScheduler()
# 定义定时任务函数
def task1():
with app.app_context():
# products = Product.query.all()
c = GetTbData()
c.get_product_info()
print("定时任务 1 执行了!")
def task2():
print("定时任务 2 执行了!")
# 添加定时任务
scheduler.add_job(task1, 'interval', seconds=10)
scheduler.add_job(task2, 'cron', hour=10, minute=31)
manage.py
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# author:zts
# date: 2023.09.05
# Blog: https://blog.csdn.net/u012452483
from app import create_app
from scheduler.tasks import scheduler
app = create_app()
if __name__ == '__main__':
app.config['JSON_AS_ASCII'] = False # 解决中文乱码问题
# 初始化 APScheduler
scheduler.start()
app.run(host='0.0.0.0', port=8989, debug=True) # 监听服务端口