python flask+apscheduler 定时任务导致数据重复和错误的解决办法
我们先看一下未定时前的代码,每一次执行数据都是准确的,是我们想要的结果
import datetime
class Num_total():
def __init__(self):
self.list1 = []
self.list2 = []
self.today = datetime.date.today().strftime('%Y-%m-%d')
def get_time(self):
print('系统当天时间:',self.today)
def get_list(self):
print('self.list1',self.list1)
print('self.list2',self.list2)
def main(self):
for i in range(5):
self.list1.append(i)
self.list2.append(i+5)
#获取生成的数据
self.get_list()
#获取当天时间
self.get_time()
if __name__ == '__main__':
num = Num_total()
num.main()
输出结果正确,每次都是这几个结果
输出结果
>>> self.list1 [0,1,2,3,4]
>>> self.list2 [5,6,7,8,9]
>>> 系统当天时间: 2022-12-14
使用flask_apscheduler定时设置
#设置定时的参数
JOB = [
{#定时任务执行计划
'id':'job1',
'func':Num_total().main(),#创建对象调用主函数
'args':None,#入参
'trigger':'cron',#设置定时执行
'hour':'17',
'minute':'12'
}
]
设置定时,第一天是正常的,第二天往后就会出现数据叠加,日期固定的问题,导致如果两个数据列表写入文件时会出现重复和叠加问题。
具体问题有两个:
第一:设置定时的时候,发现每一天的日期都是设置定时的那一天,时间被固定了
第二:第二天起文件数据出现错乱叠加问题
网上查的解决原因与方案:
Flask的重新加载器将加载应用程序两次。因此flask总共有两个进程,重新加载器监视文件系统的更改并在不同的进程中启动真实应用程序,
解决办法:
禁用重新加载器。在启动flask程序的run语句中,将添加use_reloader=False参数即可禁用重新加载器
关闭调试模式。同样地,在启动flask程序的run语句中,将debug=True改为debug=False即可关闭debug模式,在部署后真实的运行场景中都会关闭调试模式。(来源:https://blog.csdn.net/qq_47527477/article/details/122904551)
但是问题未解决
原因是定时参数里面我们用的那个 func 参数
'func':Num_total().main(),#创建对象调用主函数
相当于我们传了一个固定的对象,因为定时任务相当于程序一直启动,每天定时执行一次,都是同一个对象,所以数据还是会叠加积累,所以我们要想办法每一次执行主函数,数据都会重置和清空就解决了
我的解决方案:
把可变的参数全部放在主函数里面,变成局部变量,不管你重复调用几次,每次都会重新清空或生成,就不会出现数据累积和固定不变的问题
下面是重复数据和日期固定的复现:发现只要同一对象重复调用主函数,就会出现数据重复和日期固定,定时参数里面填写的每次调用的对象就是我们定时时创建的一直没变
import datetime
class Num_total():
def __init__(self):
self.list1 = []
self.list2 = []
self.today = datetime.date.today().strftime('%Y-%m-%d')
def get_time(self):
print('系统当天时间:',self.today)
def get_list(self):
print('self.list1',self.list1)
print('self.list2',self.list2)
def main(self):
for i in range(5):
self.list1.append(i)
self.list2.append(i+5)
#获取生成的数据
self.get_list()
#获取当天时间
self.get_time()
if __name__ == '__main__':
num = Num_total()
num.main()
num.main()#同一对象继续调用导致数据重复与日期固定,定时时对象是固定的
输出结果错误出现重复和日期固定
>>> self.list1 [0, 1, 2, 3, 4]
>>> self.list2 [5, 6, 7, 8, 9]
>>> 系统当天时间: 2022-12-14
>>> self.list1 [0, 1, 2, 3, 4, 0, 1, 2, 3, 4]
>>> self.list2 [5, 6, 7, 8, 9, 5, 6, 7, 8, 9]
>>> 系统当天时间: 2022-12-14 #模拟定时的,如果程序一直运行,第二天同一个对象调用,日期是不会变化的
代码优化,可变参数全部变成函数内部局部变量,是每次调用都是最新的值
import datetime
class Num_total():
def __init__(self):
pass
def get_time(self,today):
print('系统当天时间:',today)
def get_list(self,list1 ,list2):
print('self.list1',list1)
print('self.list2',list2)
def main(self):
list1 = []
list2 = []
today = datetime.date.today().strftime('%Y-%m-%d')
for i in range(5):
list1.append(i)
list2.append(i+5)
#获取生成的数据
self.get_list(list1,list2)
#获取当天时间
self.get_time(today)
if __name__ == '__main__':
num = Num_total()
num.main()
num.main()
结果正确
>>> self.list1 [0, 1, 2, 3, 4]
>>> self.list2 [5, 6, 7, 8, 9]
>>> 系统当天时间: 2022-12-14
>>> self.list1 [0, 1, 2, 3, 4]
>>> self.list2 [5, 6, 7, 8, 9]
>>> 系统当天时间: 2022-12-14 #同一天调用的,所以时间一致
日常总结,有错必纠。