溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶(hù)服務(wù)條款》

在django中使用apscheduler 執(zhí)行計(jì)劃任務(wù)的實(shí)現(xiàn)方法

發(fā)布時(shí)間:2020-08-26 16:06:40 來(lái)源:腳本之家 閱讀:1348 作者:mindg.cn 欄目:開(kāi)發(fā)技術(shù)

對(duì)于任何軟件開(kāi)發(fā)人員而言,為將來(lái)計(jì)劃任務(wù)都是必不可少的工具。 盡管我們創(chuàng)建的許多編程旨在響應(yīng)明確的觸發(fā)或用戶(hù)事件,但定期執(zhí)行的后臺(tái)進(jìn)程也同樣重要。

“每個(gè)星期一早晨更新結(jié)果?!?/p>

“每天晚上分批下單?!?/p>

甚至具有每日請(qǐng)求限制的第三方API也隱式要求這種行為。

“我們只能每五分鐘請(qǐng)求一次更新?!?/p>

幸運(yùn)的是,許多聰明的人已經(jīng)解決了這個(gè)問(wèn)題,并且不難找到python本地解決方案。 Advanced Python Scheduler(APS)是一個(gè)很好的選擇,它具有簡(jiǎn)單,直觀的API以及同類(lèi)產(chǎn)品中的一些最佳文檔。

對(duì)于此項(xiàng)目,我們將專(zhuān)注于將APS提供的調(diào)度技術(shù)與您的常規(guī)Django應(yīng)用程序集成:洛杉磯天氣應(yīng)用程序,該應(yīng)用程序定期輪詢(xún)第三方天氣api以進(jìn)行模型更新。

目標(biāo)是比Django教程進(jìn)行更深入的探索,同時(shí)不要在任何方向上陷入困境。

I.安裝APS和其他依賴(lài)項(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)目目錄。

為避免兩地同名的混淆,我們僅將“根目錄”稱(chēng)為“根目錄”。 讓下面的圖作為我們跳文件夾冒險(xiǎn)的路線(xiàn)圖。

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

盡管主要專(zhuān)注于演示調(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 >
 <h6>Currently in</h6>
 <h4>{{city}}</h4>
 <h5>{{temperature_in_f}} F | {{temperature_in_c}} C</h5>
 <h5>{{desctiprion}}</h5>
 <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將為您授予帶有有效電子郵件地址的訪問(wèn)令牌。

現(xiàn)在,由于它在概念上不同于我們的表示層,因此讓我們?cè)诟夸浿袆?chuàng)建一個(gè)新的ForecastUpdater文件夾。 在其中,我們將添加兩個(gè)文件:一個(gè)空白的__init__.py文件和一個(gè)ForecastApi.py文件。 請(qǐng)參閱路線(xiàn)圖以供參考。

[ 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ò)誤只是被丟棄了—過(guò)度的沉默是唯一出問(wèn)題的跡象。

其次,我們?cè)诖a中指定洛杉磯。 將您的服務(wù)器配置到所需的任何位置。

同樣重要的是要注意,update_forecast()不帶任何參數(shù)。 我們很快就會(huì)看到,我們的高級(jí)python計(jì)劃程序具有嚴(yán)格的無(wú)參數(shù)規(guī)則。 甚至帶有孤獨(dú)的self參數(shù)的方法也不會(huì)飛。

五,高級(jí)Python計(jì)劃程序

我們已經(jīng)建立了模型。 我們可以通過(guò)調(diào)用API來(lái)更新數(shù)據(jù)。 現(xiàn)在我們需要做的就是指定訪問(wèn)該API的頻率,這樣我們就可以在不超出數(shù)據(jù)訪問(wèn)限制的情況下提供合理的最新信息。

在ForecastUpdater模塊中,添加一個(gè)updater.py文件。 在這里,我們將使用Advanced Python Scheduler設(shè)置我們的預(yù)測(cè)更新的節(jié)奏。

OpenWeatherMaps使用條款允許在一個(gè)小時(shí)內(nèi)保持60個(gè)通話(huà),以保持免費(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正是這種類(lèi)型的運(yùn)行時(shí)初始化邏輯的地方。

在weather / apps.py文件中,您會(huì)找到一個(gè)名為WeatherConfig的類(lèi)的存根,該類(lèi)繼承自Django的AppConfig類(lèi)。

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開(kāi)發(fā)人員都知道的好工具。 它在直觀的API后面隱藏了非常常見(jiàn)的業(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ì)大家有所幫助!

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI