ストックドッグ

KatoTakahiro。金融系の会社で働くSEが株やPython、その他諸々について書いています。サービスも運営してます→http://fmbrain.work

herokuでのスケジュール管理にAPSchedulerを使ってみる

目次

herokuで定期的にファイルを実行したいとき何を使っていますか?

cron?

heroku scheduler?

APScheduler?

cron...?

DBの更新、データの取得、バックアップの保存などのスケジュールの管理はモダンなWebアプリには必須機能です。

ubuntuのデフォルトでインストールされているcronはあらゆるスケジューリングが可能で、上記のほとんどのことはcronによって達成することが出来ます。

ですが、cronはサーバー上で動作することもあり、Webアプリのテストをローカル環境で行うことを考えると、もっと高いレイヤーのアプリケーションのインスタンスで動作するほうが勝手がいいです。

heroku scheduler...?

herokuにはスケジュール管理のためのファンタスティックなアドオンが用意されています。

このheroku schedulerはシンプルなタスクを10分、1時間、一日、複数の間隔での実行が可能です。

しかし、5分や37分など中途半端な時間での実行は難しいです。

cronよりもheroku schedulerよりAPSchedulerが良い

アプリケーションのインスタンスで動作し、かつ、中途半端な時間でも簡単にスケジュールの管理が可能なのが、APSchedulerです。

これはPython製のライブラリなので、私のようにwebアプリを全てpythonで完結させたい人たちにはもってこいです。

heroku上でAPSchedulerを使ってみる

ということで、1分おきに現在時刻をDBにインサートするプログラムを書いてみます。

最終的な出力はこうなります。

herokuのログを見ると、1分おきにDBを更新していることがわかります。

f:id:doz13189:20170410001021p:plain

用意するもの

herokuでアプリを運用するために必要なファイルは以下です。

#適当に用意してください
runtime.txt
requirements.txt

#以下は今から作成します
Procfile
gettime.py
time.db
timeclock.py

スタート。

#screamtimeという名前のアプリを作ります
heroku create screamtime

次に、gettime.pyを作成します。

import sqlite3
import pandas as pd
import datetime


#現在時刻を取得する
now = datetime.datetime.today()
hour = now.hour
minute = now.minute

#DataFrame形式にぶち込む
#普通はSQL文書いてインサートすると思いますが、
#私がDataFrame形式に慣れているので、こちらを使用していますが、各自なれた方法でお願いします
time_df = pd.DataFrame({"Hour" : [hour], "Minute" : [minute]})


#db作成
dbname = "time.db"

#dbコネクト
conn = sqlite3.connect(dbname)
c = conn.cursor()

#dbのnameをtime_dfとし、読み込んだcsvファイルをsqlに書き込む
#if_existsでもしすでにtime_dfが存在していても、置き換えるように指示
time_df.to_sql("times", conn, if_exists="replace")

#作成したdbを見てみる
select_sql = 'select * from times'
for row in c.execute(select_sql):
    print(row)

conn.close()

これをgettime.pyという名前で保存します。

次は、今作成したgettime.pyをAPSchedulerで定期的に実行させるコードを書きます。

from apscheduler.schedulers.blocking import BlockingScheduler
import os

sched = BlockingScheduler()

#間隔は1分ごとにしています
#minutesではなくてhourに変更したら、時間での指定も可能です
@sched.scheduled_job('interval', minutes=1)
def timed_job():
	print("Let's start")
	os.system("python gettime.py")


sched.start()

これをtimeclock.pyという名前で保存します。


最後にProcfileを作成します。

clock: python timeclock.py

これで、herokuにclockのファイルであるということを宣言します。

ファイルが全て揃ったので、あとはherokuに上げるだけです。

念の為、herokuに上げるまでのgitでの手順を載せておきます。

git init
git add .
git commit -m "first commit"
git push heroku master

エラーなく行けば、これでherokuには「1分おきに現在時刻をDBにインサートするプログラム」がアップロードされました。

以下でherokuにclockをスケールします。

heroku ps:scale clock=1

上手くスケールされたことを確認して。

heroku ps
|<

数分待ってからherokuのログを見てみます。

>||
heroku logs

f:id:doz13189:20170410001021p:plain

以上で「1分おきに現在時刻をDBにインサートするプログラム」が完成しました。

まとめ

APSchedulerはとても簡単にスケジュールの管理が行うことができます。

コードもpythonで書くことができるので、使い勝手がとても良いです。

cronよりもheroku schedulerよりもAPSchedulerが良いんじゃあないでしょうか!?