A script that runs perfectly when you type python script.py in your terminal often fails silently when scheduled — not because the schedule is wrong, but because scheduled jobs don't inherit your shell's environment (PATH, virtual environments, working directory). Each platform's method is below, plus the fix for that specific problem.
01Linux/macOS: cron
Open your crontab:
crontab -e
Add a line for, say, running a script every day at 6:30 AM:
30 6 * * * /usr/bin/python3 /home/user/scripts/backup.py >> /home/user/scripts/backup.log 2>&1
Two details that matter: use the full path to both the Python interpreter and the script (find it with which python3), and redirect output to a log file — otherwise, when the job fails, you'll have no idea why.
02Windows: Task Scheduler
- Open Task Scheduler → Create Task (not "Basic Task" — it hides useful options).
- General tab: check "Run whether user is logged on or not" if it needs to work while you're logged out.
- Triggers tab: New → set your schedule.
- Actions tab: New → Program/script: the full path to
python.exe(find it withwhere pythonin Command Prompt). Add arguments: the full path to your script, in quotes. - Set "Start in" to your script's folder — this fixes relative file paths inside the script that otherwise break.
03macOS: launchd
Cron technically still works on macOS but Apple's own scheduler, launchd, is more reliable for tasks that need to survive sleep/wake cycles. Create a plist file:
nano ~/Library/LaunchAgents/com.user.backup.plist
<?xml version="1.0" encoding="UTF-8"?>
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.user.backup</string>
<key>ProgramArguments</key>
<array>
<string>/usr/bin/python3</string>
<string>/Users/you/scripts/backup.py</string>
</array>
<key>StartCalendarInterval</key>
<dict>
<key>Hour</key><integer>6</integer>
<key>Minute</key><integer>30</integer>
</dict>
</dict>
</plist>
Load it:
launchctl load ~/Library/LaunchAgents/com.user.backup.plist
04The virtual environment trap
If your script depends on packages installed in a virtual environment, calling the system Python directly will fail with ModuleNotFoundError even though it works in your terminal. Point the scheduler at the interpreter inside the venv instead:
/home/user/myproject/venv/bin/python3 /home/user/myproject/backup.py
This one line fixes the single most common reason scheduled Python jobs work manually but fail when automated.