Python3实现定时任务的四种方式

最近做一个小程序开发任务,主要负责后台部分开发;根据项目需求,需要实现三个定时任务:

1>定时更新微信token,需要2小时更新一次;

2>商品定时上线;

3>定时检测后台服务是否存活;

使用Python去实现这三个任务,这里需要使用定时相关知识点;

Python实现定点与定时任务方式比较多,找到下面四中实现方式,每个方式都有自己应用场景;下面来快速介绍Python中常用的定时任务实现方式:

1>循环+sleep;

2>线程模块中Timer类;

3>schedule模块;

4>定时框架:APScheduler

在开始之前先设定一个任务(这样不用依赖外部环境):

1:定时或者定点监测CPU与内存使用率;

2:将时间,CPU,内存使用情况保存到日志文件;

先来实现系统监测功能:

准备工作:安装psutil:pip install psutil

功能实现

#psutil:获取系统信息模块,可以获取CPU,内存,磁盘等的使用情况
import psutil
import time
import datetime
#logfile:监测信息写入文件
def MonitorSystem(logfile = None):
 #获取cpu使用情况
 cpuper = psutil.cpu_percent()
 #获取内存使用情况:系统内存大小,使用内存,有效内存,内存使用率
 mem = psutil.virtual_memory()
 #内存使用率
 memper = mem.percent
 #获取当前时间
 now = datetime.datetime.now()
 ts = now.strftime('%Y-%m-%d %H:%M:%S')
 line = f'{ts} cpu:{cpuper}%, mem:{memper}%'
 print(line)
 if logfile:
  logfile.write(line)

代码运行结果:

2019-03-21 14:23:41 cpu:0.6%, mem:77.2%

接下来我们要实现定时监测,比如3s监测一下系统资源使用情况。

最简单使用方式:sleep

这种方式最简单,直接使用while+sleep就可以实现:

def loopMonitor():
 while True:
  MonitorSystem()
  #2s检查一次
  time.sleep(3)
loopMonitor()

输出结果:

2019-03-21 14:28:42 cpu:1.5%, mem:77.6%
2019-03-21 14:28:45 cpu:1.6%, mem:77.6%
2019-03-21 14:28:48 cpu:1.4%, mem:77.6%
2019-03-21 14:28:51 cpu:1.4%, mem:77.6%
2019-03-21 14:28:54 cpu:1.3%, mem:77.6%

这种方式存在问题:只能处理单个定时任务。

如果你依然在编程的世界里迷茫,不知道自己的未来规划

自己是一名高级python开发工程师,从基础的python脚本到web开发、爬虫、django、数据挖掘等,零基础到项目实战的资料都有整理。送给每一位python的小伙伴!分享一些学习的方法和需要注意的小细节

又来了新任务:需要每秒监测网络收发字节,代码实现如下:

def MonitorNetWork(logfile = None):
 #获取网络收信息
 netinfo = psutil.net_io_counters()
 #获取当前时间
 now = datetime.datetime.now()
 ts = now.strftime('%Y-%m-%d %H:%M:%S')
 line = f'{ts} bytessent={netinfo.bytes_sent}, bytesrecv={netinfo.bytes_recv}'
 print(line)
 if logfile:
  logfile.write(line)
MonitorNetWork()

代码执行结果:

2019-03-21 14:47:21 bytessent=169752183, bytesrecv=1107900973

如果我们同时在while循环中监测两个任务会有等待问题,不能每秒监测网络情况。

Timer实现方式

timer最基本理解就是定时器,我们可以启动多个定时任务,这些定时器任务是异步执行,所以不存在等待顺序执行问题。

先来看Timer的基本使用:

导入:from threading import Timer

主要方法:

Timer方法 说明
Timer(interval, function, args=None, kwargs=None) 创建定时器
cancel() 取消定时器
start() 使用线程方式执行
join(self, timeout=None) 等待线程执行结束

定时器只能执行一次,如果需要重复执行,需要重新添加任务;

我们先来看基本使用:

from threading import Timer
#记录当前时间
print(datetime.datetime.now())
#3S执行一次
sTimer = Timer(3, MonitorSystem)
#1S执行一次
nTimer = Timer(1, MonitorNetWork)
#使用线程方式执行
sTimer.start()
nTimer.start()
#等待结束
sTimer.join()
nTimer.join()
#记录结束时间
print(datetime.datetime.now())

输出结果:

2019-03-21 15:13:36.739798
2019-03-21 15:13:37 bytessent=171337324, bytesrecv=1109002349
2019-03-21 15:13:39 cpu:1.4%, mem:93.2%
2019-03-21 15:13:39.745187

可以看到,花费时间为3S,但是我们想要做的是每秒监控网络状态;如何处理。

Timer只能执行一次,所以执行完成之后需要再次添加任务,我们对代码进行修改:

from threading import Timer
import psutil
import time
import datetime
def MonitorSystem(logfile = None):
 cpuper = psutil.cpu_percent()
 mem = psutil.virtual_memory()
 memper = mem.percent
 now = datetime.datetime.now()
 ts = now.strftime('%Y-%m-%d %H:%M:%S')
 line = f'{ts} cpu:{cpuper}%, mem:{memper}%'
 print(line)
 if logfile:
  logfile.write(line)
 #启动定时器任务,每三秒执行一次
 Timer(3, MonitorSystem).start()
def MonitorNetWork(logfile = None):
 netinfo = psutil.net_io_counters()
 now = datetime.datetime.now()
 ts = now.strftime('%Y-%m-%d %H:%M:%S')
 line = f'{ts} bytessent={netinfo.bytes_sent}, bytesrecv={netinfo.bytes_recv}'
 print(line)
 if logfile:
  logfile.write(line)
 #启动定时器任务,每秒执行一次
 Timer(1, MonitorNetWork).start()
MonitorSystem()
MonitorNetWork()

执行结果:

2019-03-21 15:18:21 cpu:1.5%, mem:93.2%
2019-03-21 15:18:21 bytessent=171376522, bytesrecv=1109124678
2019-03-21 15:18:22 bytessent=171382215, bytesrecv=1109128294
2019-03-21 15:18:23 bytessent=171384278, bytesrecv=1109129702
2019-03-21 15:18:24 cpu:1.9%, mem:93.2%
2019-03-21 15:18:24 bytessent=171386341, bytesrecv=1109131110
2019-03-21 15:18:25 bytessent=171388527, bytesrecv=1109132600
2019-03-21 15:18:26 bytessent=171390590, bytesrecv=1109134008

从时间中可以看到,这两个任务可以同时进行不存在等待问题。

Timer的实质是使用线程方式去执行任务,每次执行完后会销毁,所以不必担心资源问题。

调度模块:schedule

schedule是一个第三方轻量级的任务调度模块,可以按照秒,分,小时,日期或者自定义事件执行时间;

安装方式:

pip install schedule

我们来看一个例子:

import datetime
import schedule
import time
def func():
 now = datetime.datetime.now()
 ts = now.strftime('%Y-%m-%d %H:%M:%S')
 print('do func time :',ts)
def func2():
 now = datetime.datetime.now()
 ts = now.strftime('%Y-%m-%d %H:%M:%S')
 print('do func2 time:',ts)
def tasklist():
 #清空任务
 schedule.clear()
 #创建一个按秒间隔执行任务
 schedule.every(1).seconds.do(func)
 #创建一个按2秒间隔执行任务
 schedule.every(2).seconds.do(func2)
 #执行10S
 for i in range(10):
  schedule.run_pending()
  time.sleep(1)
tasklist()

执行结果:

do func  time : 2019-03-22 08:51:38
do func2 time: 2019-03-22 08:51:39
do func  time : 2019-03-22 08:51:39
do func  time : 2019-03-22 08:51:40
do func2 time: 2019-03-22 08:51:41
do func  time : 2019-03-22 08:51:41
do func  time : 2019-03-22 08:51:42
do func2 time: 2019-03-22 08:51:43
do func  time : 2019-03-22 08:51:43
do func  time : 2019-03-22 08:51:44
do func2 time: 2019-03-22 08:51:45
do func  time : 2019-03-22 08:51:45
do func  time : 2019-03-22 08:51:46

执行过程分析:

>1>因为在jupyter下执行,所以先将schedule任务清空;
>2>按时间间在schedule中隔添加任务;
>3>这里按照秒间隔添加func,按照两秒间隔添加func2;
>4>schedule添加任务后,需要查询任务并执行任务;
>5>为了防止占用资源,每秒查询到点任务,然后顺序执行;

第5个顺序执行怎么理解,我们修改func函数,里面添加time.sleep(2)

然后只执行func工作,输出结果:

do func  time : 2019-03-22 09:00:59
do func  time : 2019-03-22 09:01:02
do func  time : 2019-03-22 09:01:05

可以看到时间间隔为3S,为什么不是1S?

因为这个按照顺序执行,func休眠2S,循环任务查询休眠1S,所以会存在这个问题。

在我们使用这种方式执行任务需要注意这种阻塞现象。

我们看下schedule模块常用使用方法:

#schedule.every(1)创建Job, seconds.do(func)按秒间隔查询并执行
schedule.every(1).seconds.do(func)
#添加任务按分执行
schedule.every(1).minutes.do(func)
#添加任务按天执行
schedule.every(1).days.do(func)
#添加任务按周执行
schedule.every().weeks.do(func)
#添加任务每周1执行,执行时间为下周一这一时刻时间
schedule.every().monday.do(func)
#每周1,1点15开始执行
schedule.every().monday.at("12:00").do(job)

这种方式局限性:如果工作任务回非常耗时就会影响其他任务执行。我们可以考虑使用并发机制配置这个模块使用。

任务框架APScheduler

APScheduler是Python的一个定时任务框架,用于执行周期或者定时任务,

可以基于日期、时间间隔,及类似于Linux上的定时任务crontab类型的定时任务;

该该框架不仅可以添加、删除定时任务,还可以将任务存储到数据库中,实现任务的持久化,使用起来非常方便。

安装方式:pip install apscheduler

apscheduler组件及简单说明:

1>triggers(触发器):触发器包含调度逻辑,每一个作业有它自己的触发器

2>job stores(作业存储):用来存储被调度的作业,默认的作业存储器是简单地把作业任务保存在内存中,支持存储到MongoDB,Redis数据库中

3> executors(执行器):执行器用来执行定时任务,只是将需要执行的任务放在新的线程或者线程池中运行

4>schedulers(调度器):调度器是将其它部分联系在一起,对使用者提供接口,进行任务添加,设置,删除。

来看一个简单例子:

import time
from apscheduler.schedulers.blocking import BlockingScheduler
def func():
 now = datetime.datetime.now()
 ts = now.strftime('%Y-%m-%d %H:%M:%S')
 print('do func time :',ts)
def func2():
 #耗时2S
 now = datetime.datetime.now()
 ts = now.strftime('%Y-%m-%d %H:%M:%S')
 print('do func2 time:',ts)
 time.sleep(2)
def dojob():
 #创建调度器:BlockingScheduler
 scheduler = BlockingScheduler()
 #添加任务,时间间隔2S
 scheduler.add_job(func, 'interval', seconds=2, id='test_job1')
 #添加任务,时间间隔5S
 scheduler.add_job(func2, 'interval', seconds=3, id='test_job2')
 scheduler.start()
dojob()

输出结果:

do func  time : 2019-03-22 10:32:20
do func2 time: 2019-03-22 10:32:21
do func  time : 2019-03-22 10:32:22
do func  time : 2019-03-22 10:32:24
do func2 time: 2019-03-22 10:32:24
do func  time : 2019-03-22 10:32:26

输出结果中可以看到:任务就算是有延时,也不会影响其他任务执行。

APScheduler框架提供丰富接口去实现定时任务,可以去参考官方文档去查看使用方式。

最后选择:

简单总结上面四种定时定点任务实现:

1:循环+sleep方式适合简答测试,

2:timer可以实现定时任务,但是对定点任务来说,需要检查当前时间点;

3:schedule可以定点定时执行,但是需要在循环中检测任务,而且存在阻塞;

4:APScheduler框架更加强大,可以直接在里面添加定点与定时任务;

综合考虑,决定使用APScheduler框架,实现简单,只需要直接创建任务,并将添加到调度器中即可。

总结

以上所述是小编给大家介绍的Python3实现定时任务的四种方式,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对我们网站的支持!
如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!

(0)

相关推荐

  • Python3中常用的处理时间和实现定时任务的方法的介绍

    无论哪种编程语言,时间肯定都是非常重要的部分,今天来看一下python如何来处理时间和python定时任务,注意咯:本篇所讲是python3版本的实现,在python2版本中的实现略有不同,有时间会再写一篇以便大家区分. 1.计算明天和昨天的日期 #! /usr/bin/env python #coding=utf-8 # 获取今天.昨天和明天的日期 # 引入datetime模块 import datetime #计算今天的时间 today = datetime.date.today() #计算

  • 详解使用python crontab设置linux定时任务

    熟悉linux的朋友应该知道在linux中可以使用crontab设置定时任务.可以通过命令crontab -e编写任务.当然也可以直接写配置文件设置任务. 但是有时候希望通过脚本自动设置,比如我们应用程序部署时等.有需求当然就得想办法解决,不然在程序猿界混(一群自得其乐的猿). 下面进入正题,开始想通过以写文件的形式设置,通过在配置文件中直接追加一行即可.但是读写文件难免有点繁琐,再比如:设置任务时要检查任务是否已经存在:根据输入参数设置相应的任务等.以读写文件难免不太合适.所以想到了"万能&q

  • Python实现定时任务

    Python下实现定时任务的方式有很多种方式.下面介绍几种 循环sleep: 这是一种最简单的方式,在循环里放入要执行的任务,然后sleep一段时间再执行.缺点是,不容易控制,而且sleep是个阻塞函数. def timer(n): ''''' 每n秒执行一次 ''' while True: print time.strftime('%Y-%m-%d %X',time.localtime()) yourTask() # 此处为要执行的任务 time.sleep(n) threading的Time

  • python Celery定时任务的示例

    本文介绍了python Celery定时任务的示例,分享给大家,具体如下: 配置 启用Celery的定时任务需要设置CELERYBEAT_SCHEDULE . Celery的定时任务都由celery beat来进行调度.celery beat默认按照settings.py之中的时区时间来调度定时任务. 创建定时任务 一种创建定时任务的方式是配置CELERYBEAT_SCHEDULE: #每30秒调用task.add from datetime import timedelta CELERYBEA

  • Python3.6 Schedule模块定时任务(实例讲解)

    一,编程环境 PyCharm2016,Anaconda3 Python3.6 需要安装schedule模块,该模块网址:https://pypi.python.org/pypi/schedule 打开Anaconda Prompt,输入:conda install schedule 提示:Package Not Found Error 于是,使用 pip 安装.由于Anaconda3 中已经自带了pip,如下图: 于是 cmd 命令行切换到 scripts 目录,执行 pip.exe insta

  • Python中定时任务框架APScheduler的快速入门指南

    前言 大家应该都知道在编程语言中,定时任务是常用的一种调度形式,在Python中也涌现了非常多的调度模块,本文将简要介绍APScheduler的基本使用方法. 一.APScheduler介绍 APScheduler是基于Quartz的一个python定时任务框架,实现了Quartz的所有功能,使用起来十分方便.提供了基于日期.固定时间间隔以及crontab类型的任务,并且可以持久化任务. APScheduler提供了多种不同的调度器,方便开发者根据自己的实际需要进行使用:同时也提供了不同的存储机

  • Linux下Python脚本自启动与定时任务详解

    前言 最近同事问了一个关于Python脚本自启动与定时任务的问题,发现很多的朋友对这块都不是特别的熟悉,所以本文主要给大家介绍的是关于Linux下Python脚本自启动与定时任务的相关内容,分享出来供大家参考学习,话不多说了,来一起看看详细的介绍: 一.让Python随Linux开机自动运行 准备好要自启的脚本auto.py 用root权限编辑以下文件 sudo vim /ect/rc.local 在exit 0上面编辑启动脚本的命令 /usr/bin/python3.5 /home/edgar

  • Python3实现定时任务的四种方式

    最近做一个小程序开发任务,主要负责后台部分开发:根据项目需求,需要实现三个定时任务: 1>定时更新微信token,需要2小时更新一次: 2>商品定时上线: 3>定时检测后台服务是否存活: 使用Python去实现这三个任务,这里需要使用定时相关知识点: Python实现定点与定时任务方式比较多,找到下面四中实现方式,每个方式都有自己应用场景:下面来快速介绍Python中常用的定时任务实现方式: 1>循环+sleep: 2>线程模块中Timer类: 3>schedule模块

  • python 实现定时任务的四种方式

    用Python实现定时任务 有些时候我们需要每隔一段时间就要执行一段程序,或者是往复循环执行某一个任务.比如博主在上篇文章讲的爬虫一样,在实现对某个目标进行在线爬取的话,也需要用到实时任务. 用Python实现定时任务的四种方法 while True: + sleep() threading.Timer定时器 调度模块schedule 任务框架APScheduler 定时要完成的Task(简单定义下) import datetime def Task(): now = datetime.date

  • java 创建线程的四种方式

    1.继承Thread类方式 这种方式适用于执行特定任务,并且需要获取处理后的数据的场景. 举例:一个用于累加数组内数据的和的线程. public class AdditionThread extends Thread { private int sum = 0; private int[] nums; ​ public AdditionThread(int[] nums, String threadName) { super(threadName); this.nums = nums; } ​

  • Python命令行参数化的四种方式详解

    目录 1. sys.argv 2. argparse 3. getopt 4. click 最后 大家好,在日常编写 Python 脚本的过程中,我们经常需要结合命令行参数传入一些变量参数,使项目使用更加的灵活方便 本篇文章我将罗列出构建 Python 命令行参数的 4 种常见方式 它们分别是: 内置 sys.argv 模块 内置 argparse 模块 内置 getopt 模块 第三方依赖库 click 1. sys.argv 构建命令行参数最简单.常见的方式是利用内置的「 sys.argv

  • JSP向后台传递参数的四种方式总结

    Jsp页面传值的方法 一.通过Form表单提交传值 客户端通过Form表单提交到服务器端,服务器端通过 Java代码 request.getParameter(String xx); 来取得参数(xx)为参数名称. 通过get/post方式进行提交 二.通过隐藏域传值 通过在表单中加入一个隐藏域来提交到服务器端,这种方式的好处是可以在客户端加入一些自己想要加入的参数,以便得到相应的值. 客户端代码: Java代码 <input type="hidden" name="i

  • linux下实现web数据同步的四种方式(性能比较)

    实现web数据同步的四种方式 ======================================= 1.nfs实现web数据共享2.rsync +inotify实现web数据同步3.rsync+sersync更快更节约资源实现web数据同步4.unison+inotify实现web数据双向同步 ======================================= 一.nfs实现web数据共享 nfs能实现数据同步是通过NAS(网络附加存储),在服务器上共享一个文件,且服务器需

  • 横向对比分析Python解析XML的四种方式

    在最初学习PYTHON的时候,只知道有DOM和SAX两种解析方法,但是其效率都不够理想,由于需要处理的文件数量太大,这两种方式耗时太高无法接受. 在网络搜索后发现,目前应用比较广泛,且效率相对较高的ElementTree也是一个比较多人推荐的算法,于是拿这个算法来实测对比,ElementTree也包括两种实现,一个是普通ElementTree(ET),一个是ElementTree.iterparse(ET_iter). 本文将对DOM.SAX.ET.ET_iter四种方式进行横向对比,通过处理相

  • 详细分析Javascript中创建对象的四种方式

    前言 使用Javascript创建对象的方式有很多,现在就来列举一下其中的四种方式,并且罗列出了每种方式的优缺点,可以让大家进行选择使用,下面来看看. 工厂模式 function createPerson(name, age){ var obj = new Object(); obj.name = name; obj.age = age; return obj; //一定要返回,否则打印undefined:undefined } var person1 = new createPerson('Y

  • Python函数中定义参数的四种方式

    Python中函数参数的定义主要有四种方式: 1. F(arg1,arg2,-) 这是最常见的定义方式,一个函数可以定义任意个参数,每个参数间用逗号分割,用这种方式定义的函数在调用的的时候也必须在函数名后的小括号里提供个数相等 的值(实际参数),而且顺序必须相同,也就是说在这种调用方式中,形参和实参的个数必须一致,而且必须一一对应,也就是说第一个形参对应这第一个实参.例如: 复制代码 代码如下: def a(x,y):print x,y 调用该函数,a(1,2)则x取1,y取2,形参与实参相对应

  • javascript中类的定义方式详解(四种方式)

    本文实例讲述了javascript中类的定义方式.分享给大家供大家参考,具体如下: 类的定义包括四种方式: 1.工厂方式 function createCar(name,color,price){ var tempcar=new Object; tempcar.name=name; tempcar.color=color; tempcar.price=price; tempcar.getName=function(){ document.write(this.name+"-----"+

随机推荐