在django中使用apscheduler 執(zhí)行計(jì)劃任務(wù)的實(shí)現(xiàn)方法
對(duì)于任何軟件開發(fā)人員而言,為將來(lái)計(jì)劃任務(wù)都是必不可少的工具。 盡管我們創(chuàng)建的許多編程旨在響應(yīng)明確的觸發(fā)或用戶事件,但定期執(zhí)行的后臺(tái)進(jìn)程也同樣重要。
“每個(gè)星期一早晨更新結(jié)果?!?/p>
“每天晚上分批下單?!?/p>
甚至具有每日請(qǐng)求限制的第三方API也隱式要求這種行為。
“我們只能每五分鐘請(qǐng)求一次更新。”
幸運(yùn)的是,許多聰明的人已經(jīng)解決了這個(gè)問題,并且不難找到python本地解決方案。 Advanced Python Scheduler(APS)是一個(gè)很好的選擇,它具有簡(jiǎn)單,直觀的API以及同類產(chǎn)品中的一些最佳文檔。
對(duì)于此項(xiàng)目,我們將專注于將APS提供的調(diào)度技術(shù)與您的常規(guī)Django應(yīng)用程序集成:洛杉磯天氣應(yīng)用程序,該應(yīng)用程序定期輪詢第三方天氣api以進(jìn)行模型更新。
目標(biāo)是比Django教程進(jìn)行更深入的探索,同時(shí)不要在任何方向上陷入困境。
I.安裝APS和其他依賴項(xiàng)
在您的項(xiàng)目目錄中,創(chuàng)建一個(gè)虛擬環(huán)境并激活它
virtualenv env . env/bin/activate
根據(jù)本指南安裝和配置PostgreSQL。 在此階段,我們只需要在您的計(jì)算機(jī)上啟動(dòng)并運(yùn)行SQL管理器即可。
另外,我發(fā)現(xiàn)使用PgAdmin PostgreSQL GUI有幫助。 在您的計(jì)算機(jī)上進(jìn)行設(shè)置的詳細(xì)信息可以在這里找到(使用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
在這個(gè)新目錄(根目錄)中,您將看到另一個(gè)名為advancedScheduler的文件夾。 這是Django項(xiàng)目目錄。
為避免兩地同名的混淆,我們僅將“根目錄”稱為“根目錄”。 讓下面的圖作為我們跳文件夾冒險(xiǎn)的路線圖。
[ super_project_directory/ ] | +----[ env/ ] <-- Virtualenv stuff | +----[ advancedScheduler/ ] <-- the Root Directory | +----[ advancedScheduler/ ] <-- the Django Project Directory | +----[ weather/ ] <-- the Django App Directory
盡管主要專注于演示調(diào)度程序的功能,但讓我們花點(diǎn)時(shí)間連接Django應(yīng)用。
我們首先要將天氣應(yīng)用添加到項(xiàng)目的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' ]
接下來(lái),將新的網(wǎng)址格式添加到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()) ]
在天氣應(yīng)用程序目錄中創(chuàng)建一個(gè)模板文件夾。 將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})
三, 建立數(shù)據(jù)庫(kù)連接并遷移模型
在advancedScheduler / settings.py中,將DATABASES值更改為:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': 'advancedScheduler',
'USER': 'some_user_name',
'PASSWORD': 'some_password',
'HOST': 'localhost',
'PORT': '',
}
}
您應(yīng)該從上述PostgreSQL配置指南(此處和此處)了解USER,PASSWORD和PORT的值。
與PostgreSQL建立連接后,就該遷移我們的模型了。 導(dǎo)航到“根目錄”并鍵入:
python manage.py makemigrations python manage.py migrate
這樣,我們的模型應(yīng)該已經(jīng)映射到數(shù)據(jù)庫(kù)了。 繼續(xù)并檢查所有內(nèi)容。 不用擔(dān)心,我會(huì)在這里等你回來(lái)。
IV。 預(yù)測(cè)API
時(shí)間到了有趣的部分。 我正在從OpenWeatherMap(一個(gè)免費(fèi)的天氣API)中提取我的預(yù)報(bào)數(shù)據(jù),該API將為您授予帶有有效電子郵件地址的訪問令牌。
現(xiàn)在,由于它在概念上不同于我們的表示層,因此讓我們?cè)诟夸浿袆?chuàng)建一個(gè)新的ForecastUpdater文件夾。 在其中,我們將添加兩個(gè)文件:一個(gè)空白的__init__.py文件和一個(gè)ForecastApi.py文件。 請(qǐng)參閱路線圖以供參考。
[ 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
在這里,有一些事情要注意。 異常處理遠(yuǎn)非健壯。 錯(cuò)誤只是被丟棄了—過度的沉默是唯一出問題的跡象。
其次,我們?cè)诖a中指定洛杉磯。 將您的服務(wù)器配置到所需的任何位置。
同樣重要的是要注意,update_forecast()不帶任何參數(shù)。 我們很快就會(huì)看到,我們的高級(jí)python計(jì)劃程序具有嚴(yán)格的無(wú)參數(shù)規(guī)則。 甚至帶有孤獨(dú)的self參數(shù)的方法也不會(huì)飛。
五,高級(jí)Python計(jì)劃程序
我們已經(jīng)建立了模型。 我們可以通過調(diào)用API來(lái)更新數(shù)據(jù)。 現(xiàn)在我們需要做的就是指定訪問該API的頻率,這樣我們就可以在不超出數(shù)據(jù)訪問限制的情況下提供合理的最新信息。
在ForecastUpdater模塊中,添加一個(gè)updater.py文件。 在這里,我們將使用Advanced Python Scheduler設(shè)置我們的預(yù)測(cè)更新的節(jié)奏。
OpenWeatherMaps使用條款允許在一個(gè)小時(shí)內(nèi)保持60個(gè)通話,以保持免費(fèi)等級(jí); 每五分鐘更新一次就足夠了。
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()
這可能是您可以找到的最簡(jiǎn)單的APS實(shí)現(xiàn)。 如果您查看他們的網(wǎng)站或GitHub上的幾個(gè)工作示例,則將發(fā)現(xiàn)一個(gè)完整的功能和設(shè)置工具箱,您可以使用這些工具來(lái)進(jìn)行計(jì)時(shí),以使其盡可能的細(xì)致。
按照我們想要的方式配置了調(diào)度程序后,就可以將其連接到Django應(yīng)用了。
理想情況下,我們希望在調(diào)度程序上按一次播放,然后讓它執(zhí)行其任務(wù)。 我們需要一種一致且可靠的方式來(lái)初始化時(shí)間表一次且僅一次。 對(duì)于我們而言,Django正是這種類型的運(yùn)行時(shí)初始化邏輯的地方。
在weather / apps.py文件中,您會(huì)找到一個(gè)名為WeatherConfig的類的存根,該類繼承自Django的AppConfig類。
class WeatherConfig(AppConfig): name = 'weather'
為了讓Django知道它需要在啟動(dòng)時(shí)啟動(dòng)更新程序,我們覆蓋了AppConfig.ready()方法。
from django.apps import AppConfig class WeatherConfig(AppConfig): name = 'weather' def ready(self): from forecastUpdater import updater updater.start()
重要的是要記住,由于繼承的復(fù)雜性,此覆蓋的任何導(dǎo)入都必須位于ready()方法的主體內(nèi)。 Django還警告不要在我們的覆蓋中直接與數(shù)據(jù)庫(kù)進(jìn)行交互; 生產(chǎn),調(diào)試,風(fēng)雨無(wú)阻,每次啟動(dòng)天氣應(yīng)用程序時(shí),都會(huì)執(zhí)行此代碼。
最后,我們現(xiàn)在需要在advancedScheduler / settings.py中再次更新INSTALLED_APPS變量。 Django需要知道我們要使用自定義配置來(lái)運(yùn)行天氣應(yīng)用。
INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'weather.apps.WeatherConfig' ]
VI。 全部放在一起
而已。 在這一點(diǎn)上,我們可以啟動(dòng)我們的應(yīng)用程序,然后讓更新程序執(zhí)行其操作。
python manage.py runserver --noreload
-noreload標(biāo)志可防止Django啟動(dòng)天氣應(yīng)用的第二個(gè)實(shí)例-這是調(diào)試模式下的默認(rèn)行為。 第二個(gè)實(shí)例意味著我們所有計(jì)劃的任務(wù)將觸發(fā)兩次。
最初,我們的結(jié)果看起來(lái)不完整。 由于我們將更新程序邏輯安排為每五分鐘運(yùn)行一次,因此我們不停地抽動(dòng)一下……為了使事情變得有趣,縮短審慎刷新之間的間隔可能是明智的選擇,或者在初始化時(shí)調(diào)用一次update_forecast()。
七。 最后的想法
我們做到了! 我們的天氣應(yīng)用已準(zhǔn)備好與世界分享(請(qǐng)?jiān)诖颂幉榭次业男畔ⅲ?/p>
Advanced Python Scheduler是任何Python開發(fā)人員都知道的好工具。 它在直觀的API后面隱藏了非常常見的業(yè)務(wù)需求的復(fù)雜性。 考慮一下,安裝程序只用了三行代碼。
該項(xiàng)目的真正技巧是與Django框架進(jìn)行交互-配置,遷移,初始化。 然后,任務(wù)自動(dòng)化成為事后的想法。 五分鐘內(nèi)您就完成了。
https://github.com/kmhoran/la-weather-app
以上所述是小編給大家介紹的在django中使用apscheduler 執(zhí)行計(jì)劃任務(wù)的實(shí)現(xiàn)方法,希望對(duì)大家有所幫助!
相關(guān)文章
python通過安裝itchat包實(shí)現(xiàn)微信自動(dòng)回復(fù)收到的春節(jié)祝福
這篇文章主要介紹了python通過安裝itchat包實(shí)現(xiàn)微信自動(dòng)回復(fù)收到的春節(jié)祝福,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友參考下吧2020-01-01
輕松實(shí)現(xiàn)TensorFlow微信跳一跳的AI
這篇文章主要教大家如何輕松實(shí)現(xiàn)TensorFlow微信跳一跳的AI,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-01-01
Python?頁(yè)面解析Beautiful?Soup庫(kù)的使用方法
Beautiful?Soup?簡(jiǎn)稱?BS4(其中?4?表示版本號(hào))是一個(gè)?Python?中常用的頁(yè)面解析庫(kù),它可以從?HTML?或?XML?文檔中快速地提取指定的數(shù)據(jù),這篇文章主要介紹了springboot?集成?docsify?實(shí)現(xiàn)隨身文檔?,需要的朋友可以參考下2022-09-09
Django中和時(shí)區(qū)相關(guān)的安全問題詳解
這篇文章主要給大家介紹了關(guān)于Django中和時(shí)區(qū)相關(guān)的安全問題的相關(guān)資料,需要的朋友可以參考下2020-10-10
python實(shí)現(xiàn)微信發(fā)送郵件關(guān)閉電腦功能
這篇文章主要介紹了python實(shí)現(xiàn)微信發(fā)送郵件關(guān)閉電腦功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-02-02
關(guān)于Python面向?qū)ο缶幊痰闹R(shí)點(diǎn)總結(jié)
Python從設(shè)計(jì)之初就已經(jīng)是一門面向?qū)ο蟮恼Z(yǔ)言,正因?yàn)槿绱?,在Python中創(chuàng)建一個(gè)類和對(duì)象是很容易的。下面這篇文章將詳細(xì)給大家介紹關(guān)于Python面向?qū)ο缶幊痰闹R(shí)點(diǎn),需要的朋友可以參考借鑒,下面來(lái)一起看看吧。2017-02-02

