The Quiet Terminal

← Practical Tips

Five ways to run a Python script on a schedule

2026-06-26 · 3 min read

I have a backup script I'm fond of. For its first year of life, the main thing running it was me remembering to run it. A script on a schedule is a different species from a script you run by hand — it has to survive you closing the laptop, rebooting, and forgetting it exists. These are the five ways I've tried, and where each one belongs.

1. cron

# crontab -e — run backup.py every day at 06:30
30 6 * * * /usr/bin/python3 /home/me/scripts/backup.py >> /home/me/backup.log 2>&1

Five time fields, minute first, and the operating system starts the job whether or not you're logged in. The redirect at the end isn't decoration: cron throws output away, and your only debugging tool is the log you bothered to set up. Downside: crontab syntax is a small language I relearn every single time, and it doesn't exist on stock Windows.

2. Windows Task Scheduler

schtasks /create /tn "NightlyBackup" /tr "python C:\me\scripts\backup.py" /sc daily /st 06:30

Same idea with a Windows accent: a GUI full of checkboxes, or this one command. It can wake the PC to run the job, which is more than a sleeping laptop running cron will promise. Same rule applies — write your own log file inside the script, because the scheduler won't keep your output for you.

3. while True and sleep

import time
import backup

while True:
    backup.run()
    time.sleep(6 * 60 * 60)

The pure-Python answer, and it has three honest flaws: the schedule drifts, because each cycle is run-time plus six hours; one unhandled exception ends the loop forever, silently; and closing the terminal ends everything. It's fine for a demo and fine when the script is already long-running and this is merely one of its duties. As a scheduler, it's a placeholder.

4. the sched module

import sched
import time

scheduler = sched.scheduler(time.time, time.sleep)

def backup():
    print("running backup")
    scheduler.enter(6 * 60 * 60, priority=1, action=backup)

scheduler.enter(0, priority=1, action=backup)
scheduler.run()

Standard library, no dependencies, precise timing — the job reschedules itself inside a priority queue. But it's still one process, with all the fragility of while-and-sleep attached. Its natural home isn't "every day at 6:30" but "in twenty minutes, do X" inside a program that's running anyway.

5. APScheduler

from apscheduler.schedulers.blocking import BlockingScheduler

scheduler = BlockingScheduler()

@scheduler.scheduled_job("cron", hour=6, minute=30)
def backup():
    print("running backup")

scheduler.start()

Third-party, pip install apscheduler. Cron-style schedules written as Python, several jobs in one process, sane behavior when the machine was asleep at the appointed time. The limit is the same as 3 and 4: it schedules work within your program, not within your computer — the process still has to be alive.

The verdict

My backup script runs under cron now, and the honest opinion that got it there: if the schedule matters more than the code, put the schedule in the operating system and let Python stay a program that runs when it's told.