Pythonの定期的実行:Cronとscheduleモジュール
Cron
cron(crontab)とは、ジョブ管理コマンドで、指定された日時、もしくは時間間隔でジョブを実行する。実行されるジョブは、crontab(cron table)でスケジュールされる。
このcrontabには、cronジョブのスケジュールが書き込まれ、その書式は以下のようになる。
* * * * * echo ‘Hello’ >> /tmp/test.txt
最初の5つの$${*}$$は実行時間日時で、この後にコマンドをかく。
cronジョブの実行に関してのユーザー制限は、
/usr/lib/cron/cron.deny
/usr/lib/cron/cron.allow
で、制御される。このファイルの持ち主は当然ながらrootである。
crontab コマンド
crontabのファイルの記述は
%crontab -e
で行う。記述形式はvi仕様である。
実行中のcronジョブの一覧と中身は、
% crontab -l
* * * * * echo ‘Hello’ >> /tmp/test.txt
で確認できる。
cronジョブの停止、crontabの削除は
% crontab -r
で行われる。ただし、cronは毎分crontabの変更を確認し、変更されたものを実行するため、crontabの中身を変更しても再起動は必要ない。
crontabのジョブ指定には、crontab -eで直接書き込む方法のほかに、スクリプトで指定することも可能である。
% cat ./script.sh
* * * * * echo ‘Hello’ >> /tmp/test.txt
% crontab < ./script.sh
crontab syntaxs
crontabの時間指定は以下のようになっている。
* * * * * echo ‘Hello’ >> /tmp/test.txt
| | | | |
| | | | days of week(0-6) 0:sunday
| | | month(1-12)
| | day of the month(1-31)
| hour(0-23)
min(0-59)
毎日の午後6時半に、/home/users/tempのディレクトリにあるファイルを全て消去するcrontabは、
30 18 * * * rm /home/users/tmp/*
毎日午前11時に行う場合は、
0 11 * * rm /home/users/tmp/*
1月、6月の1日、00:30に行う場合、
30 0 1 1,6 * rm /home/users/tmp/*
毎月の1日、10日、15日の00:00に行う場合
0 0 1,10,15 * * rm /home/users/tmp/*
13日の金曜日、00:05と00:10に行う場合
5,10 0 13 * 5 rm /home/users/tmp/*
15分毎にあるスクリプトを実行する時には、
*/15 * * * * /path/to/script.sh
月曜から金曜日までの15分毎にスクリプトを実行する場合、
*/15 * * * 1-5 /path/to/script.sh
crontab enviroment
cronジョブは、ターミナルを経由して実行されるわけではないので、環境指定はcrontab内で行う必要がある。また、実行ディレクトリは、cronジョブを指定したユーザーのホームディレクトリとなる。
crontabの環境にzshを指定したい場合、実行スクリプトに書き込み、さらにanacondaで指定したpythonを仕様したい場合はcrontabで、condaを初期化(initiate)するために、source ~/.zshrcを行ってから、condaの環境をアクティベイトする。その後に、pythonファイルを実行すれば良い。
SHELL=/bin/zsh
* * * * * source $PWD/.zshrc; conda activate your_env >> /tmp/cronpy.log 2>&1; python3 /path/to/file/main.py >> /tmp/cronpy.txt 2>&1
出力ファイルの/tmp/cronpy.logに続く$${2>&1}$$で、標準出力と標準エラー出力の両方をフィアルに書き込む。
scheduleモジュール
Jupyter notebook やPythonコード内で定期的実行を行うには、scheduleを使う。scheduleのインストールは以下の通り。
pip install schedule
定期実行の関数を指定する。
import time
import datetime
from schedule import every, repeat, run_pending, CancelJob
def job1():
print("Hello",datetime.datetime.now())
def job2(name):
print('Hi',name,datetime.datetime.now())
def job3():
print("Good Morning",datetime.datetime.now())
schedule.every(1).seconds.do(job1) # 関数job1を、1秒毎に実行する
schedule.every(2).minutes.do(job1) # 関数job1を、2分毎に実行する
schedule.every(3).hours.do(job1) # 関数job1を、2時間毎に実行する
schedule.every(4).days.do(job1) # 関数job1を、4日毎に実行する
schedule.every(5).weeks.do(job1) # 関数job1を、5週間毎に実行する
schedule.every(6).months.do(job1) # 関数job1を、2時間毎に実行する
schedule.every().minute.at(":7").do(job3) # 関数job3を、毎分7秒に実行する
schedule.every().hour.at(":8").do(job3) # 関数job3を、毎時間8分に実行する
schedule.every(5).hours.at("9:10").do(job3) # 関数job3を、5時間毎の9分10秒に実行する
schedule.every().day.at("11:12").do(job3) # 関数job3を、毎日11時12分に実行する
schedule.every().monday.do(job3) # 関数job3を、毎月曜日に実行する
schedule.every().tuesday.at("9:10").do(job3) # 関数job3を、毎火曜日の9分10秒に実行する
schedule.every(2).seconds.do(jobs, name='Bob')# 関数job2を、引数Bobで2秒毎に実行する
定期的実行のジョブと繰り返し時間間隔を指定したのちに、ループで実行する。同日正午まで実行したい場合場合は、以下のように実行する。
year = date.today().year
month = date.today().month
hour = 12
minute = 0
second = 0
set_until_time = datetime(year,month,date.today().day,hour,minute,second)
while datetime.now() < set_until_time:
run_pending()
time.sleep(1)
この記事が気に入ったらサポートをしてみませんか?