您好,登錄后才能下訂單哦!
對(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ì)大家有所幫助!
免責(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)容。