Every developer has scripts that need to run periodically: database backups, log rotation, data scraping, report generation. While cron works, it is opaque, hard to test, and lives outside your codebase. The schedule library lets you write pure Python automation that is readable, version-controlled, and easy to debug.

Installation

pip install schedule

A Simple Scheduled Task

import schedule
import time

def job():
    print("Running scheduled task...")

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

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

Real-World Example: Automated Backup

import schedule
import time
import shutil
import os
from datetime import datetime

BACKUP_SRC = "/var/www/myapp/data"
BACKUP_DST = "/backups"

def backup_data():
    timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
    archive = os.path.join(BACKUP_DST, f"backup_{timestamp}.tar.gz")
    shutil.make_archive(archive.replace(".tar.gz", ""), 'gztar', BACKUP_SRC)
    print(f"Backup created: {archive}")

    # Keep only last 7 backups
    files = sorted(os.listdir(BACKUP_DST))
    while len(files) > 7:
        os.remove(os.path.join(BACKUP_DST, files.pop(0)))

schedule.every().day.at("02:00").do(backup_data)

print("Scheduler running...")
while True:
    schedule.run_pending()
    time.sleep(60)

Running as a Systemd Service

Instead of keeping a terminal open, run your scheduler as a systemd service:

[Unit]
Description=Python Task Scheduler
After=network.target

[Service]
Type=simple
User=www-data
WorkingDirectory=/var/www/myapp
ExecStart=/var/www/myapp/.venv/bin/python scheduler.py
Restart=always

[Install]
WantedBy=multi-user.target

Why Schedule Over Cron?

FeatureCronSchedule (Python)
Readable syntaxNoYes
Unit testableNoYes
Error handlingManualNative try/except
Version controlCrontab is separateIn your repo
Cross-platformUnix onlyAnywhere Python runs

Next Steps

  • Add logging with Python's logging module instead of print
  • Send failure alerts via email or webhook
  • Use threading to run multiple scheduled jobs concurrently