How to Schedule Python Scripts: Automate Tasks with Cron and Schedule Library
You have built amazing Python automation scripts — file organizers, web scrapers, email bots — but they only run when you manually execute them. The missing piece is scheduling: making your scripts run automatically at specific times without any human intervention. This is what separates a useful script from a fully automated system.
In this guide, you will learn how to schedule Python scripts using the schedule library for simple in-process scheduling and cron jobs (Linux/macOS) or Task Scheduler (Windows) for system-level automation. This is the final step in your Python automation journey.
Why Schedule Python Scripts?
Scheduling turns one-time scripts into ongoing automation systems. Instead of remembering to run your file organizer every evening, it runs automatically at 9 PM. Instead of manually checking prices, your web scraper runs every hour and sends you an email alert when something changes.
Common scheduling use cases include daily data backups, hourly price monitoring, weekly report generation, periodic file cleanup, daily email digests, and regular database maintenance tasks.
Method 1: The Python schedule Library
The schedule library is the simplest way to add scheduling to your Python scripts. It runs inside your Python process and offers a clean, readable API.
Installation
pip install schedule
Basic Usage
import schedule
import time
def job():
print("Running scheduled task...")
# Your automation code here
# Run every 10 minutes
schedule.every(10).minutes.do(job)
# Run every hour
schedule.every().hour.do(job)
# Run daily at a specific time
schedule.every().day.at("09:00").do(job)
# Run every Monday
schedule.every().monday.at("08:30").do(job)
# Run every 2 hours
schedule.every(2).hours.do(job)
print("Scheduler started. Press Ctrl+C to stop.")
while True:
schedule.run_pending()
time.sleep(1)
Practical Example: Scheduled File Organizer
import schedule
import time
import os
import shutil
import logging
logging.basicConfig(
filename="scheduler.log",
level=logging.INFO,
format="%(asctime)s - %(message)s"
)
def organize_downloads():
downloads = os.path.expanduser("~/Downloads")
categories = {
"Images": [".jpg", ".png", ".gif", ".svg", ".webp"],
"Documents": [".pdf", ".docx", ".txt", ".xlsx"],
"Videos": [".mp4", ".avi", ".mkv", ".mov"],
"Archives": [".zip", ".rar", ".tar", ".gz"]
}
moved = 0
for filename in os.listdir(downloads):
filepath = os.path.join(downloads, filename)
if os.path.isdir(filepath):
continue
_, ext = os.path.splitext(filename)
ext = ext.lower()
dest_folder = "Other"
for cat, exts in categories.items():
if ext in exts:
dest_folder = cat
break
cat_path = os.path.join(downloads, dest_folder)
os.makedirs(cat_path, exist_ok=True)
try:
shutil.move(filepath, os.path.join(cat_path, filename))
moved += 1
except Exception as e:
logging.error("Failed to move " + filename + ": " + str(e))
logging.info("Organized " + str(moved) + " files")
print("Organized " + str(moved) + " files")
# Schedule to run every day at 9 PM
schedule.every().day.at("21:00").do(organize_downloads)
print("File organizer scheduled for 9 PM daily.")
while True:
schedule.run_pending()
time.sleep(60)
Running Multiple Scheduled Tasks
import schedule
import time
def morning_report():
print("Generating morning report...")
def hourly_price_check():
print("Checking prices...")
def weekly_backup():
print("Running weekly backup...")
def daily_cleanup():
print("Cleaning up temp files...")
schedule.every().day.at("08:00").do(morning_report)
schedule.every().hour.do(hourly_price_check)
schedule.every().sunday.at("02:00").do(weekly_backup)
schedule.every().day.at("23:00").do(daily_cleanup)
print("All tasks scheduled.")
print("Pending jobs:")
for job in schedule.get_jobs():
print(" -", job)
while True:
schedule.run_pending()
time.sleep(1)
Method 2: Cron Jobs on Linux and macOS
Cron is a built-in Unix/Linux/macOS scheduler that runs commands at specified intervals. Unlike the schedule library, cron runs at the system level — your script does not need to be running continuously.
Understanding Cron Syntax
Cron uses a five-field syntax to specify when a command should run:
# Cron format:
# minute hour day_of_month month day_of_week command
# 0-59 0-23 1-31 1-12 0-7
# Examples:
# Run every day at 9 AM
0 9 * * * /usr/bin/python3 /home/user/scripts/organizer.py
# Run every hour
0 * * * * /usr/bin/python3 /home/user/scripts/price_check.py
# Run every Monday at 8:30 AM
30 8 * * 1 /usr/bin/python3 /home/user/scripts/weekly_report.py
# Run every 15 minutes
*/15 * * * * /usr/bin/python3 /home/user/scripts/monitor.py
# Run at midnight on the 1st of every month
0 0 1 * * /usr/bin/python3 /home/user/scripts/monthly_backup.py
Setting Up a Cron Job
Open your crontab editor:
crontab -e
Add your scheduled task at the end of the file. Make sure to use the full path to your Python interpreter and your script. You can find your Python path by running which python3 in your terminal.
# Run file organizer every day at 9 PM
0 21 * * * /usr/bin/python3 /home/user/scripts/organize_files.py >> /home/user/scripts/cron.log 2>&1
The >> /path/to/cron.log 2>&1 part redirects both output and errors to a log file, which is essential for debugging cron jobs since cron does not display output.
Common Cron Pitfalls
Environment variables are not loaded. Cron runs with a minimal environment, so your .env file and PATH may not be available. Use absolute paths for everything and load environment variables explicitly in your script.
Working directory is different. Cron does not set the working directory to your script location. Use os.chdir() at the start of your script or use absolute paths for all file operations.
import os
import sys
# Set working directory to script location
script_dir = os.path.dirname(os.path.abspath(__file__))
os.chdir(script_dir)
# Now load .env from the script directory
from dotenv import load_dotenv
load_dotenv(os.path.join(script_dir, ".env"))
Method 3: Windows Task Scheduler
On Windows, use Task Scheduler to run Python scripts automatically. Open Task Scheduler from the Start menu, click "Create Basic Task," and follow the wizard. Set the trigger to your desired schedule and set the action to "Start a program" with the following settings:
Program: Path to python.exe (e.g., C:\Python312\python.exe)
Arguments: Path to your script (e.g., C:\Scripts\organizer.py)
Start in: Your script directory (e.g., C:\Scripts)
You can also create tasks via the command line:
schtasks /create /tn "PythonOrganizer" /tr "python C:\Scripts\organizer.py" /sc daily /st 21:00
Making Your Scripts Production-Ready
Add Proper Logging
import logging
from datetime import datetime
def setup_logging(log_file="automation.log"):
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s [%(levelname)s] %(message)s",
handlers=[
logging.FileHandler(log_file),
logging.StreamHandler()
]
)
return logging.getLogger(__name__)
logger = setup_logging()
logger.info("Script started")
try:
# Your automation code
logger.info("Task completed successfully")
except Exception as e:
logger.error("Task failed: " + str(e))
Add Error Notifications
Combine logging with email alerts to get notified when a scheduled task fails:
def run_with_error_notification(task_func, task_name):
try:
task_func()
logger.info(task_name + " completed successfully")
except Exception as e:
error_msg = task_name + " failed: " + str(e)
logger.error(error_msg)
send_email(
"admin@example.com",
"Automation Error: " + task_name,
error_msg
)
Running as a Background Service
For scripts that use the schedule library and need to run continuously, you can use tools like nohup on Linux or create a systemd service:
# Run in background with nohup
nohup python3 scheduler.py &
# Or create a systemd service file: /etc/systemd/system/python-scheduler.service
[Unit]
Description=Python Automation Scheduler
After=network.target
[Service]
User=youruser
WorkingDirectory=/home/youruser/scripts
ExecStart=/usr/bin/python3 scheduler.py
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target
# Enable and start the service
sudo systemctl enable python-scheduler
sudo systemctl start python-scheduler
sudo systemctl status python-scheduler
Choosing the Right Scheduling Method
Use the schedule library when you want simple, readable Python-only scheduling, need to run multiple tasks from one script, and want fine-grained control within your Python code.
Use cron jobs when you need system-level reliability, want the script to run even after a reboot (with @reboot directive), and need the scheduling to be independent of your Python process.
Use Windows Task Scheduler when you are on Windows and need the same system-level reliability that cron provides on Unix systems.
Conclusion
Scheduling is the capstone skill that transforms individual automation scripts into fully autonomous systems. Whether you use the Python schedule library for simplicity or cron jobs for robustness, the ability to run scripts automatically on a schedule is what makes Python automation truly powerful.
Combined with the skills from our other guides — file organization, web scraping, and email automation — you now have a complete automation toolkit. Return to our Python Automation Pillar Guide for the full learning path and additional project ideas.
تعليقات
إرسال تعليق