【Python】スケジュール実行を自動化する(schedule/cron連携)

Python

こんにちは、かつコーチです。

「毎朝9時にレポートを作成したい」「1時間おきにデータを取得したい」。
定期的に同じ処理を繰り返したい場面は、業務の自動化でよく出てきます。

そのたびに手動でスクリプトを実行するのは非効率です。
この記事では、Pythonのscheduleライブラリを使った定期実行の方法を解説します。

あわせて、より本格的な運用で使われるcron(macOS/Linux)・タスクスケジューラ(Windows)との連携イメージも紹介します。
記事を読み終える頃には、自分のスクリプトを自動で動かす仕組みが作れるようになっているはずです。

scheduleライブラリとは?

スケジュール実行を簡単に書けるライブラリ

scheduleライブラリとは、Pythonのコード内で「いつ・何を実行するか」を直感的に書けるサードパーティ製ライブラリです。

サードパーティ製とは、Python本体には含まれておらず、別途インストールが必要なライブラリのことです。
標準ライブラリのtimedatetimeだけでも定期実行は書けますが、条件分岐が増えて読みにくくなりがちです。

scheduleライブラリを使うと「毎日10時に実行する」のような処理を、英語の文章のように読みやすく書けます。

なぜscheduleが必要なのか

Pythonのスクリプトは、実行した瞬間に処理が終わればプログラムも終了します。
つまり、何もしなければ「1回だけ実行して終わり」です。

定期的に処理を繰り返すには、スクリプト自体をずっと起動させたままにするか、OSの機能で繰り返し起動する仕組みが必要です。
scheduleライブラリは前者の「起動させたまま繰り返す」アプローチを、シンプルなコードで実現してくれます。

基本の書き方

インストール

まずはscheduleライブラリをインストールします。

pip install schedule

Python 3.12系で動作確認しています。

手順1:毎日決まった時刻に実行する

もっとも基本的な使い方は、毎日決まった時刻に関数を実行することです。

import schedule
import time


def job():
    print("レポートを作成しました")


schedule.every().day.at("09:00").do(job)

while True:
    schedule.run_pending()
    time.sleep(1)

schedule.every().day.at("09:00").do(job)で、毎日9時にjob関数を実行するよう予約します。
while Trueループの中でschedule.run_pending()を呼び続けることで、予約された時刻が来たら処理が実行されます。

手順2:一定間隔で繰り返し実行する

「毎日◯時」ではなく「◯分おき」「◯時間おき」に実行したい場合もあります。

import schedule
import time


def check_status():
    print("ステータスを確認しました")


schedule.every(10).minutes.do(check_status)
schedule.every(1).hours.do(check_status)
schedule.every().monday.at("08:00").do(check_status)

while True:
    schedule.run_pending()
    time.sleep(1)

schedule.every(10).minutesで10分おき、schedule.every().mondayで毎週月曜日、といった具合に指定できます。
複数のスケジュールを同時に登録することも可能です。

つまずきやすい設定・注意点

scheduleライブラリは、あくまでプロセスが起動し続けていることが前提です。
while Trueループを含むスクリプト自体が終了してしまうと、それ以降は何も実行されません。

ノートPCをスリープさせたり、ターミナルを閉じてスクリプトが終了したりすると、当然スケジュールも止まります。
本番運用では、後述するcronやタスクスケジューラと組み合わせるか、サーバー上でプロセスを常駐させる仕組み(systemdなど)が必要になります。

よくあるつまずきポイント・エラー対処

sleepを入れずにCPUを占有してしまう

Before(つまずいたコード)

import schedule
import time


def job():
    print("処理を実行しました")


schedule.every().day.at("09:00").do(job)

while True:
    schedule.run_pending()

私は最初、time.sleep()を入れ忘れてこのコードを実行してしまいました。
数秒後にPCのファンが唸り出し、慌ててタスクマネージャーを確認するとPythonプロセスがCPUを100%近く使っていました。

while Trueループが休みなくrun_pending()を呼び続けるため、CPUリソースを無駄に消費してしまうのです。

After(改善したコード)

import schedule
import time


def job():
    print("処理を実行しました")


schedule.every().day.at("09:00").do(job)

while True:
    schedule.run_pending()
    time.sleep(1)

time.sleep(1)を1行加えるだけで、1秒に1回のチェックになりCPU負荷が大幅に下がります。
while Trueでポーリングするコードを書くときは、必ずsleepを入れる習慣をつけましょう。

実行タイミングがずれる・想定通りに動かない

Before(つまずいたコード)

import schedule

schedule.every().day.at("9:00").do(lambda: print("実行"))

このコードを実行すると、次のエラーが出ます。

schedule.exceptions.ScheduleValueError: Invalid time format for a daily job (valid format is HH:MM(:SS)?)

"9:00"のように時刻を1桁で書いてしまうと、フォーマットエラーになります。

After(改善したコード)

import schedule

schedule.every().day.at("09:00").do(lambda: print("実行"))

"09:00"のように、時刻部分は必ず2桁(0埋め)で指定します。
一見小さなミスですが、動かないコードのデバッグに時間を取られやすいポイントなので覚えておくと安心です。

cron・タスクスケジューラとの連携イメージ

macOS/Linuxではcronで起動する方法もある

scheduleライブラリは「プロセスを常駐させる」方式でしたが、もう1つの選択肢がcronです。
cronとは、macOSやLinuxに標準搭載されている、指定した時刻にコマンドを自動実行する仕組みです。

cronを使う場合、Pythonスクリプト側にはループを書かず、1回実行したら終了するシンプルな作りにします。

# report.py
def job():
    print("レポートを作成しました")


if __name__ == "__main__":
    job()

そしてcrontab(cronの設定ファイル)に、実行タイミングを登録します。

# crontab -e で編集
0 9 * * * /usr/bin/python3 /path/to/report.py

0 9 * * *は「毎日9時0分」を表すcronの書式です。
OS側が起動タイミングを管理してくれるため、Pythonプロセスを常駐させ続ける必要がありません。

Windowsではタスクスケジューラを使う

Windowsの場合はcronの代わりにタスクスケジューラというGUIツールがあります。
タスクスケジューラとは、Windowsに標準搭載された、指定した条件でプログラムを自動実行する機能です。

「タスクの作成」からトリガー(毎日9時など)とアクション(pythonコマンドの実行)を設定するだけで、cronと同様のことが実現できます。

scheduleとcron、どちらを選ぶべきか

観点scheduleライブラリcron/タスクスケジューラ
プロセスの常駐必要不要
設定のしやすさPythonコードで完結OSの設定が別途必要
PCの再起動・スリープ耐性弱い(プロセスが止まると停止)強い(OSが管理)
向いている用途開発中の検証、軽量な常駐アプリ本番運用、サーバー上の定期処理

開発中の検証や、Pythonコード内でスケジュール管理を完結させたい場合はscheduleライブラリが手軽です。
一方で、サーバー上で確実に動かし続けたい本番運用では、cronやタスクスケジューラに処理を委ねる方が安定します。

まとめ

この記事のポイント

  • scheduleライブラリを使うと、Pythonコード内で読みやすくスケジュール実行を書けます
  • while Trueループとtime.sleep()をセットで使うのを忘れないようにしましょう
  • 時刻指定は"09:00"のように2桁で書かないとエラーになります
  • 本番運用ではcron(macOS/Linux)・タスクスケジューラ(Windows)と組み合わせるのが安定します

次に読むべき記事

ファイル操作の自動化と組み合わせたい方は、osモジュールの解説記事もあわせてご覧ください。
PDFファイルの自動処理に興味がある方は、PyPDF2の記事も参考になります。

タグ: Python, 中級者向け, 自動化

タイトルとURLをコピーしました