在django中使用apscheduler 执行计划任务的实现方法


Posted in Python onFebruary 11, 2020

对于任何软件开发人员而言,为将来计划任务都是必不可少的工具。 尽管我们创建的许多编程旨在响应明确的触发或用户事件,但定期执行的后台进程也同样重要。

“每个星期一早晨更新结果。”

“每天晚上分批下单。”

甚至具有每日请求限制的第三方API也隐式要求这种行为。

“我们只能每五分钟请求一次更新。”

幸运的是,许多聪明的人已经解决了这个问题,并且不难找到python本地解决方案。 Advanced Python Scheduler(APS)是一个很好的选择,它具有简单,直观的API以及同类产品中的一些最佳文档。

对于此项目,我们将专注于将APS提供的调度技术与您的常规Django应用程序集成:洛杉矶天气应用程序,该应用程序定期轮询第三方天气api以进行模型更新。

目标是比Django教程进行更深入的探索,同时不要在任何方向上陷入困境。

I.安装APS和其他依赖项

在您的项目目录中,创建一个虚拟环境并激活它

virtualenv env
. env/bin/activate

根据本指南安装和配置PostgreSQL。 在此阶段,我们只需要在您的计算机上启动并运行SQL管理器即可。

另外,我发现使用PgAdmin PostgreSQL GUI有帮助。 在您的计算机上进行设置的详细信息可以在这里找到(使用Python3)。

使用pip安装所有必需的软件包(注意,psycopg2适用于PostgreSQL):

pip install apscheduler django psycopg2 requests
II. Build your app
Create a new Django project:

django-admin.py startproject advancedScheduler
cd advancedScheduler
python manage.py startapp weather

在这个新目录(根目录)中,您将看到另一个名为advancedScheduler的文件夹。 这是Django项目目录。

为避免两地同名的混淆,我们仅将“根目录”称为“根目录”。 让下面的图作为我们跳文件夹冒险的路线图。

[ super_project_directory/ ]
|
+----[ env/ ] <-- Virtualenv stuff
|
+----[ advancedScheduler/ ] <-- the Root Directory
 |
 +----[ advancedScheduler/ ] <-- the Django Project Directory
 |
 +----[ weather/ ] <-- the Django App Directory

尽管主要专注于演示调度程序的功能,但让我们花点时间连接Django应用。

我们首先要将天气应用添加到项目的INSTALLED_APPS中。 该文件位于advancedScheduler / settings.py文件中。

INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'weather'
]

接下来,将新的网址格式添加到advancedScheduler / urls.py文件中:

path('', include('weather.urls'))

毫不奇怪,我们的下一步将是将该urls.py文件添加到weather app目录中。 将以下代码包含在weather / urls.py中:

from django.conf.urls import url
from weather import views
urlpatterns = [
 url(r'^$', views.MainPage.as_view())
]

在天气应用程序目录中创建一个模板文件夹。 将index.html文件添加到此新文件夹。

以下是我们的MTV。

模型

from django.db import models
from datetime import datetime 
 
class Forecast(models.Model):
 timestamp = models.DateTimeField()
 temperatue = models.DecimalField(max_digits=12,decimal_places=2)
 description = models.CharField(max_length=150)
 city = models.CharField(max_length=150)
 
 def save(self, *args, **kwargs):
 if not self.id:
  self.timestamp = datetime.utcnow()
 return super(Forecast, self).save(*args, **kwargs)
Template
<div style="text-align: center">
 <h5>Currently in</h5>
 <h3>{{city}}</h3>
 <h4>{{temperature_in_f}} F | {{temperature_in_c}} C</h4>
 <h4>{{desctiprion}}</h4>
 <p><em>Last updated {{utc_update_time}} GMT</em></p>
</div>
View
import decimal
from datetime import datetime 
from django.shortcuts import render
from django.views.generic import TemplateView
from weather.models import Forecast 
class MainPage(TemplateView):
 def get(self, request, **kwargs):
 
 latest_forecast = Forecast.objects.latest('timestamp')
 city = latest_forecast.city
 temperature_in_c = latest_forecast.temperatue
 temperature_in_f = (latest_forecast.temperatue * decimal.Decimal(1.8)) + 32
 description = latest_forecast.description.capitalize
 timestamp = "{t.year}/{t.month:02d}/{t.day:02d} - {t.hour:02d}:{t.minute:02d}:{t.second:02d}".format( t=latest_forecast.timestamp)
 return render(
  request, 
  'index.html', 
  {
  'city':city,
  'temperature_in_c': temperature_in_c,
  'temperature_in_f': round(temperature_in_f,2),
  'desctiprion': description,
  'utc_update_time': timestamp})

三, 建立数据库连接并迁移模型

在advancedScheduler / settings.py中,将DATABASES值更改为:

DATABASES = {
 'default': {
 'ENGINE': 'django.db.backends.postgresql_psycopg2',
 'NAME': 'advancedScheduler',
 'USER': 'some_user_name',
 'PASSWORD': 'some_password',
 'HOST': 'localhost',
 'PORT': '',
 }
}

您应该从上述PostgreSQL配置指南(此处和此处)了解USER,PASSWORD和PORT的值。

与PostgreSQL建立连接后,就该迁移我们的模型了。 导航到“根目录”并键入:

python manage.py makemigrations
python manage.py migrate

这样,我们的模型应该已经映射到数据库了。 继续并检查所有内容。 不用担心,我会在这里等你回来。

IV。 预测API

时间到了有趣的部分。 我正在从OpenWeatherMap(一个免费的天气API)中提取我的预报数据,该API将为您授予带有有效电子邮件地址的访问令牌。

现在,由于它在概念上不同于我们的表示层,因此让我们在根目录中创建一个新的ForecastUpdater文件夹。 在其中,我们将添加两个文件:一个空白的__init__.py文件和一个ForecastApi.py文件。 请参阅路线图以供参考。

[ super_project_directory/ ]
|
+----[ env/ ]
|
+----[ advancedScheduler/ ] <-- the Root Directory
 |
 +----[ advancedScheduler/ ] 
 |
 +----[ weather/ ] 
 |
 +----[ forecastUpdater/ ] <-- the new Updater Module
  |
  +----< __init__.py > <--+
  |    |-- two new Python files
  +----< forecastApi.py > <--+
import requests
from weather.models import Forecast
 
def _get_forecast_json():
 url = 'http://api.openweathermap.org/data/2.5/weather'
 encoded_city_name = 'Los%20Angeles'
 country_code = 'us'
 access_token = 'your_access_token'
 
 r = requests.get('{0}?q={1},{2}&APPID={3}'.format(
 url, 
 encoded_city_name, 
 country_code, 
 access_token))
 
 try:
 r.raise_for_status()
 return r.json()
 except:
 return None
 
 
def update_forecast():
 json = _get_forecast_json()
 if json is not None:
 try:
  new_forecast = Forecast()
  
  # open weather map gives temps in Kelvin. We want celsius.  
  temp_in_celsius = json['main']['temp'] - 273.15
  new_forecast.temperatue = temp_in_celsius
  new_forecast.description = json['weather'][0]['description']
  new_forecast.city = json['name']
  new_forecast.save()
  print("saving...\n" + new_forecast)
 except:
  pass

在这里,有一些事情要注意。 异常处理远非健壮。 错误只是被丢弃了—过度的沉默是唯一出问题的迹象。

其次,我们在代码中指定洛杉矶。 将您的服务器配置到所需的任何位置。

同样重要的是要注意,update_forecast()不带任何参数。 我们很快就会看到,我们的高级python计划程序具有严格的无参数规则。 甚至带有孤独的self参数的方法也不会飞。

五,高级Python计划程序

我们已经建立了模型。 我们可以通过调用API来更新数据。 现在我们需要做的就是指定访问该API的频率,这样我们就可以在不超出数据访问限制的情况下提供合理的最新信息。

在ForecastUpdater模块中,添加一个updater.py文件。 在这里,我们将使用Advanced Python Scheduler设置我们的预测更新的节奏。

OpenWeatherMaps使用条款允许在一个小时内保持60个通话,以保持免费等级; 每五分钟更新一次就足够了。

from datetime import datetime
from apscheduler.schedulers.background import BackgroundScheduler
from forecastUpdater import forecastApi
 
def start():
 scheduler = BackgroundScheduler()
 scheduler.add_job(forecastApi.update_forecast, 'interval', minutes=5)
 scheduler.start()

这可能是您可以找到的最简单的APS实现。 如果您查看他们的网站或GitHub上的几个工作示例,则将发现一个完整的功能和设置工具箱,您可以使用这些工具来进行计时,以使其尽可能的细致。

按照我们想要的方式配置了调度程序后,就可以将其连接到Django应用了。

理想情况下,我们希望在调度程序上按一次播放,然后让它执行其任务。 我们需要一种一致且可靠的方式来初始化时间表一次且仅一次。 对于我们而言,Django正是这种类型的运行时初始化逻辑的地方。

在weather / apps.py文件中,您会找到一个名为WeatherConfig的类的存根,该类继承自Django的AppConfig类。

class WeatherConfig(AppConfig):
 name = 'weather'

为了让Django知道它需要在启动时启动更新程序,我们覆盖了AppConfig.ready()方法。

from django.apps import AppConfig
class WeatherConfig(AppConfig):
 name = 'weather'
 def ready(self):
 from forecastUpdater import updater
 updater.start()

重要的是要记住,由于继承的复杂性,此覆盖的任何导入都必须位于ready()方法的主体内。 Django还警告不要在我们的覆盖中直接与数据库进行交互; 生产,调试,风雨无阻,每次启动天气应用程序时,都会执行此代码。

最后,我们现在需要在advancedScheduler / settings.py中再次更新INSTALLED_APPS变量。 Django需要知道我们要使用自定义配置来运行天气应用。

INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'weather.apps.WeatherConfig' 
]

VI。 全部放在一起

而已。 在这一点上,我们可以启动我们的应用程序,然后让更新程序执行其操作。

python manage.py runserver --noreload

-noreload标志可防止Django启动天气应用的第二个实例-这是调试模式下的默认行为。 第二个实例意味着我们所有计划的任务将触发两次。

最初,我们的结果看起来不完整。 由于我们将更新程序逻辑安排为每五分钟运行一次,因此我们不停地抽动一下……为了使事情变得有趣,缩短审慎刷新之间的间隔可能是明智的选择,或者在初始化时调用一次update_forecast()。

七。 最后的想法

我们做到了! 我们的天气应用已准备好与世界分享(请在此处查看我的信息)。

Advanced Python Scheduler是任何Python开发人员都知道的好工具。 它在直观的API后面隐藏了非常常见的业务需求的复杂性。 考虑一下,安装程序只用了三行代码。

该项目的真正技巧是与Django框架进行交互-配置,迁移,初始化。 然后,任务自动化成为事后的想法。 五分钟内您就完成了。

https://github.com/kmhoran/la-weather-app

以上所述是小编给大家介绍的在django中使用apscheduler 执行计划任务的实现方法,希望对大家有所帮助!

Python 相关文章推荐
Python中无限元素列表的实现方法
Aug 18 Python
Python GUI布局尺寸适配方法
Oct 11 Python
Python实现微信自动好友验证,自动回复,发送群聊链接方法
Feb 21 Python
django 中QuerySet特性功能详解
Jul 25 Python
浅谈Django2.0 加xadmin踩的坑
Nov 15 Python
Python 利用邮件系统完成远程控制电脑的实现(关机、重启等)
Nov 19 Python
Tensorflow中tf.ConfigProto()的用法详解
Feb 06 Python
python 实现图片修复(可用于去水印)
Nov 19 Python
python 实现图片批量压缩的示例
Dec 18 Python
DjangoRestFramework 使用 simpleJWT 登陆认证完整记录
Jun 22 Python
详解Python内置模块Collections
Mar 22 Python
Python万能模板案例之matplotlib绘制甘特图
Apr 13 Python
django在保存图像的同时压缩图像示例代码详解
Feb 11 #Python
Python中包的用法及安装
Feb 11 #Python
使用Python实现牛顿法求极值
Feb 10 #Python
关于TensorFlow新旧版本函数接口变化详解
Feb 10 #Python
TensorFlow 多元函数的极值实例
Feb 10 #Python
给 TensorFlow 变量进行赋值的方式
Feb 10 #Python
Python 中的pygame安装与配置教程详解
Feb 10 #Python
You might like
如何跨站抓取别的站点的页面的补充
2006/10/09 PHP
PHP表单提交后引号前自动加反斜杠的原因及三种办法关闭php魔术引号
2015/09/30 PHP
浅析PHP数据导出知识点
2018/02/17 PHP
jQuery 技巧小结
2010/04/02 Javascript
JavaScript 对任意元素,自定义右键菜单的实现方法
2013/05/08 Javascript
下拉列表选择项的选中在不同浏览器中的兼容性问题探讨
2013/09/18 Javascript
如何判断元素是否为HTMLElement元素
2013/12/06 Javascript
学习Javascript面向对象编程之封装
2016/02/23 Javascript
AngularJS之依赖注入模拟实现
2016/08/19 Javascript
jquery实现图片轮播器
2017/05/23 jQuery
Node.JS使用Sequelize操作MySQL的示例代码
2017/10/09 Javascript
原生JavaScrpit中异步请求Ajax实现方法
2017/11/03 Javascript
JS实现全屏预览F11功能的示例代码
2018/07/23 Javascript
JS高级技巧(简洁版)
2018/07/29 Javascript
详解webpack之图片引入-增强的file-loader:url-loader
2018/10/08 Javascript
JS根据json数组多个字段排序及json数组常用操作
2019/06/06 Javascript
浅谈js数组splice删除某个元素爬坑
2020/10/14 Javascript
python获取Linux下文件版本信息、公司名和产品名的方法
2014/10/05 Python
python3.6 实现AES加密的示例(pyCryptodome)
2018/01/10 Python
Python3.6.0+opencv3.3.0人脸检测示例
2018/05/25 Python
python3写的简单本地文件上传服务器实例
2018/06/04 Python
Python神奇的内置函数locals的实例讲解
2019/02/22 Python
新闻专业应届生求职信
2013/10/31 职场文书
自荐信格式技巧有哪些呢
2013/11/19 职场文书
园林施工员岗位职责
2013/12/11 职场文书
纪念建党演讲稿范文
2014/01/13 职场文书
活动邀请函范文
2014/01/19 职场文书
蜜蜂引路教学反思
2014/02/04 职场文书
助残日活动总结
2014/08/27 职场文书
2015年房产经纪人工作总结
2015/05/15 职场文书
事业单位岗位说明书
2015/10/08 职场文书
小学大队委竞选口号
2015/12/25 职场文书
2016年优秀少先队员事迹材料
2016/02/26 职场文书
离婚协议书范本(2016最新版)
2016/03/18 职场文书
如何撰写促销方案?
2019/07/05 职场文书
MySQL学习总结-基础架构概述
2021/04/05 MySQL