AutomateMyJob
Back to BlogPython Automation

Schedule Python Scripts to Run Automatically: Complete Guide

Alex Rodriguez11 min read

Schedule Python Scripts to Run Automatically: Complete Guide

You've built a Python script that saves hours of work. But you still have to remember to run it. Every day. Or every Monday. Or the first of each month.

That's not true automation. Let's fix it.

Today you'll learn to schedule scripts to run automatically—no human intervention required.

What You'll Learn

  • Using Task Scheduler on Windows
  • Using cron on macOS/Linux
  • Python-based scheduling with schedule library
  • Running scripts at startup
  • Handling errors and logging for unattended execution

Prerequisites

  • Python 3.8 or higher
  • A Python script you want to schedule
  • Administrator access to your computer

The Problem

Manual script execution means:

  • You have to remember to run it
  • If you're sick, on vacation, or busy—it doesn't run
  • Timing is inconsistent
  • You waste time on routine execution

The Solution

System schedulers that run your scripts automatically:

  • Windows: Task Scheduler
  • macOS/Linux: cron
  • Cross-platform: Python schedule library or systemd

Method 1: Windows Task Scheduler

Task Scheduler is built into Windows and perfect for automation.

Step 1: Find Your Python Path

First, we need to know where Python is installed:

cmd
1where python

Copy the path (e.g., C:\Users\YourName\AppData\Local\Programs\Python\Python311\python.exe)

Step 2: Create the Scheduled Task

  1. Press Win + R, type taskschd.msc, press Enter
  2. Click Create Basic Task in the right panel
  3. Name: "Daily Report Generator" (or whatever describes your script)
  4. Description: "Runs the Python report script every day at 8 AM"
  5. Click Next

Step 3: Set the Trigger

  1. Choose when: Daily, Weekly, or Monthly
  2. Set the start time (e.g., 8:00 AM)
  3. For daily: set recurrence (every 1 day)
  4. Click Next

Step 4: Set the Action

  1. Select Start a program
  2. Click Next
  3. Program/script: Paste your Python path C:\Users\YourName\AppData\Local\Programs\Python\Python311\python.exe
  4. Add arguments: Full path to your script "C:\Scripts\my_automation.py"
  5. Start in (optional): Your script's directory C:\Scripts
  6. Click Next, then Finish

Step 5: Configure Additional Settings

  1. Find your task in Task Scheduler Library
  2. Right-click → Properties
  3. General tab: Check "Run whether user is logged on or not"
  4. Conditions tab: Uncheck "Start only if computer is on AC power" for laptops
  5. Settings tab: Check "Run task as soon as possible after a scheduled start is missed"

Testing Your Task

Right-click the task → Run to test immediately.

Method 2: macOS/Linux with cron

Cron is the standard scheduler for Unix systems.

Step 1: Open the Crontab Editor

bash
1crontab -e

This opens your personal crontab in the default editor (usually nano or vim).

Step 2: Understand Cron Syntax

Prompt
* * * * * command
│ │ │ │ │
│ │ │ │ └── Day of week (0-7, where 0 and 7 are Sunday)
│ │ │ └──── Month (1-12)
│ │ └────── Day of month (1-31)
│ └──────── Hour (0-23)
└────────── Minute (0-59)

Step 3: Add Your Schedule

Common schedule examples:

bash
1# Run every day at 8:00 AM
20 8 * * * /usr/bin/python3 /home/user/scripts/my_script.py
3
4# Run every Monday at 9:00 AM
50 9 * * 1 /usr/bin/python3 /home/user/scripts/weekly_report.py
6
7# Run every hour
80 * * * * /usr/bin/python3 /home/user/scripts/hourly_check.py
9
10# Run every 15 minutes
11*/15 * * * * /usr/bin/python3 /home/user/scripts/monitor.py
12
13# Run first day of every month at midnight
140 0 1 * * /usr/bin/python3 /home/user/scripts/monthly_report.py
15
16# Run Monday through Friday at 6 PM
170 18 * * 1-5 /usr/bin/python3 /home/user/scripts/end_of_day.py

Step 4: Save and Verify

Save the crontab (in nano: Ctrl+O, Enter, Ctrl+X)

Verify your crontab:

bash
1crontab -l

Important: Use Full Paths

Cron runs in a minimal environment. Always use:

  • Full path to Python: /usr/bin/python3
  • Full path to your script: /home/user/scripts/my_script.py

Find your Python path:

bash
1which python3

Cron Output and Logging

By default, cron sends output via email. Redirect to a log file instead:

bash
10 8 * * * /usr/bin/python3 /home/user/scripts/my_script.py >> /home/user/logs/my_script.log 2>&1

The 2>&1 redirects errors to the same file.

Method 3: Python schedule Library

For cross-platform scheduling or when you need more control:

bash
1pip install schedule

Basic Usage

python
1#!/usr/bin/env python3
2"""
3Scheduled Task Runner - Run functions on a schedule.
4Author: Alex Rodriguez
5"""
6
7import schedule
8import time
9from datetime import datetime
10
11
12def job_daily_report():
13    """Example job: Generate daily report."""
14    print(f"[{datetime.now()}] Running daily report...")
15    # Your automation code here
16    
17
18def job_hourly_check():
19    """Example job: Hourly system check."""
20    print(f"[{datetime.now()}] Running hourly check...")
21    # Your automation code here
22
23
24def job_weekly_backup():
25    """Example job: Weekly backup."""
26    print(f"[{datetime.now()}] Running weekly backup...")
27    # Your automation code here
28
29
30# Schedule the jobs
31schedule.every().day.at("08:00").do(job_daily_report)
32schedule.every().hour.do(job_hourly_check)
33schedule.every().monday.at("06:00").do(job_weekly_backup)
34
35# Also supports:
36# schedule.every(10).minutes.do(job)
37# schedule.every().wednesday.at("13:15").do(job)
38# schedule.every().day.at("10:30:00").do(job)  # With seconds
39
40
41def main():
42    """Run the scheduler."""
43    print("Scheduler started. Press Ctrl+C to exit.")
44    print(f"Scheduled jobs: {len(schedule.get_jobs())}")
45    
46    for job in schedule.get_jobs():
47        print(f"  - {job}")
48    
49    while True:
50        schedule.run_pending()
51        time.sleep(60)  # Check every minute
52
53
54if __name__ == "__main__":
55    main()

Running schedule as a Service

The schedule library requires the Python script to keep running. Use it with:

Windows: Run as a background service with pythonw.exe Linux/macOS: Run with nohup or as a systemd service

bash
1# Keep running after terminal closes
2nohup python3 scheduler.py &

Making Scripts Robust for Unattended Execution

When scripts run without supervision, they need proper error handling and logging.

Add Logging

python
1#!/usr/bin/env python3
2"""
3Robust Automation Script - With logging and error handling.
4Author: Alex Rodriguez
5"""
6
7import logging
8import sys
9from datetime import datetime
10from pathlib import Path
11
12
13# Set up logging
14def setup_logging(log_file=None):
15    """Configure logging for unattended execution."""
16    
17    if log_file is None:
18        # Log to script directory
19        script_dir = Path(__file__).parent
20        log_file = script_dir / "automation.log"
21    
22    logging.basicConfig(
23        level=logging.INFO,
24        format='%(asctime)s - %(levelname)s - %(message)s',
25        handlers=[
26            logging.FileHandler(log_file),
27            logging.StreamHandler(sys.stdout)  # Also print to console
28        ]
29    )
30    
31    return logging.getLogger(__name__)
32
33
34def main():
35    """Main function with error handling."""
36    logger = setup_logging()
37    
38    logger.info("=" * 50)
39    logger.info("Script started")
40    
41    try:
42        # Your automation code here
43        logger.info("Processing data...")
44        
45        # Example: Simulate work
46        result = process_data()
47        logger.info(f"Processing complete: {result}")
48        
49        logger.info("Script completed successfully")
50        
51    except FileNotFoundError as e:
52        logger.error(f"File not found: {e}")
53        sys.exit(1)
54        
55    except PermissionError as e:
56        logger.error(f"Permission denied: {e}")
57        sys.exit(1)
58        
59    except Exception as e:
60        logger.exception(f"Unexpected error: {e}")
61        sys.exit(1)
62
63
64def process_data():
65    """Example processing function."""
66    return "100 records processed"
67
68
69if __name__ == "__main__":
70    main()

Add Email Notifications for Failures

python
1import smtplib
2from email.mime.text import MIMEText
3
4
5def send_error_notification(error_message, script_name):
6    """Send email when script fails."""
7    
8    sender = "alerts@yourcompany.com"
9    recipient = "admin@yourcompany.com"
10    
11    msg = MIMEText(f"""
12    Script Failure Alert
13    
14    Script: {script_name}
15    Time: {datetime.now()}
16    Error: {error_message}
17    
18    Please investigate.
19    """)
20    
21    msg['Subject'] = f"[ALERT] Script Failed: {script_name}"
22    msg['From'] = sender
23    msg['To'] = recipient
24    
25    try:
26        with smtplib.SMTP('smtp.yourcompany.com', 587) as server:
27            server.starttls()
28            server.login(sender, "password")
29            server.send_message(msg)
30    except Exception as e:
31        logging.error(f"Could not send alert email: {e}")
32
33
34# In your main() function:
35try:
36    # Your code
37    pass
38except Exception as e:
39    logger.exception(f"Script failed: {e}")
40    send_error_notification(str(e), "my_script.py")
41    sys.exit(1)

The Complete Robust Script Template

python
1#!/usr/bin/env python3
2"""
3Scheduled Automation Script Template
4Author: Alex Rodriguez
5
6A robust template for scripts that run unattended on a schedule.
7Includes logging, error handling, and optional notifications.
8"""
9
10import logging
11import os
12import sys
13from datetime import datetime
14from pathlib import Path
15
16# Configuration
17SCRIPT_NAME = "automation_script"
18LOG_RETENTION_DAYS = 30
19ENABLE_EMAIL_ALERTS = False
20ALERT_EMAIL = "admin@company.com"
21
22
23def setup_logging():
24    """Set up logging with rotation."""
25    # Create logs directory
26    log_dir = Path(__file__).parent / "logs"
27    log_dir.mkdir(exist_ok=True)
28    
29    # Log file with date
30    log_file = log_dir / f"{SCRIPT_NAME}_{datetime.now():%Y%m%d}.log"
31    
32    # Configure logging
33    logging.basicConfig(
34        level=logging.INFO,
35        format='%(asctime)s | %(levelname)-8s | %(message)s',
36        datefmt='%Y-%m-%d %H:%M:%S',
37        handlers=[
38            logging.FileHandler(log_file, encoding='utf-8'),
39            logging.StreamHandler(sys.stdout)
40        ]
41    )
42    
43    logger = logging.getLogger(SCRIPT_NAME)
44    
45    # Clean old logs
46    cleanup_old_logs(log_dir)
47    
48    return logger
49
50
51def cleanup_old_logs(log_dir, days=LOG_RETENTION_DAYS):
52    """Remove log files older than specified days."""
53    import time
54    
55    cutoff = time.time() - (days * 86400)
56    
57    for log_file in log_dir.glob("*.log"):
58        if log_file.stat().st_mtime < cutoff:
59            log_file.unlink()
60
61
62def send_alert(subject, message):
63    """Send an alert email (implement based on your email setup)."""
64    if not ENABLE_EMAIL_ALERTS:
65        return
66    
67    # Add your email sending code here
68    # See our email automation guide for full implementation
69    pass
70
71
72def validate_environment():
73    """Check that required resources are available."""
74    logger = logging.getLogger(SCRIPT_NAME)
75    
76    # Example: Check required directories exist
77    required_dirs = ["data", "output"]
78    script_dir = Path(__file__).parent
79    
80    for dir_name in required_dirs:
81        dir_path = script_dir / dir_name
82        if not dir_path.exists():
83            logger.warning(f"Creating missing directory: {dir_path}")
84            dir_path.mkdir(exist_ok=True)
85    
86    # Example: Check required files exist
87    # required_files = ["config.json"]
88    # for file_name in required_files:
89    #     if not (script_dir / file_name).exists():
90    #         raise FileNotFoundError(f"Required file missing: {file_name}")
91    
92    return True
93
94
95def run_automation():
96    """
97    Main automation logic.
98    
99    CUSTOMIZE THIS FUNCTION for your specific task.
100    """
101    logger = logging.getLogger(SCRIPT_NAME)
102    
103    # Your automation code goes here
104    logger.info("Starting automation task...")
105    
106    # Example steps:
107    # 1. Read input data
108    logger.info("Step 1: Reading input data")
109    # data = read_input()
110    
111    # 2. Process data
112    logger.info("Step 2: Processing data")
113    # results = process(data)
114    
115    # 3. Save output
116    logger.info("Step 3: Saving output")
117    # save_output(results)
118    
119    # Return summary
120    return {
121        "status": "success",
122        "records_processed": 100,
123        "output_file": "output/results.xlsx"
124    }
125
126
127def main():
128    """Main entry point with full error handling."""
129    
130    # Initialize logging
131    logger = setup_logging()
132    
133    logger.info("=" * 60)
134    logger.info(f"STARTING: {SCRIPT_NAME}")
135    logger.info(f"Time: {datetime.now()}")
136    logger.info("=" * 60)
137    
138    exit_code = 0
139    
140    try:
141        # Validate environment
142        validate_environment()
143        
144        # Run the automation
145        result = run_automation()
146        
147        # Log success
148        logger.info("-" * 60)
149        logger.info("COMPLETED SUCCESSFULLY")
150        logger.info(f"Result: {result}")
151        logger.info("-" * 60)
152        
153    except FileNotFoundError as e:
154        logger.error(f"File not found: {e}")
155        send_alert(f"[ERROR] {SCRIPT_NAME}", f"File not found: {e}")
156        exit_code = 1
157        
158    except PermissionError as e:
159        logger.error(f"Permission denied: {e}")
160        send_alert(f"[ERROR] {SCRIPT_NAME}", f"Permission denied: {e}")
161        exit_code = 1
162        
163    except Exception as e:
164        logger.exception(f"Unexpected error: {e}")
165        send_alert(f"[CRITICAL] {SCRIPT_NAME}", f"Unexpected error: {e}")
166        exit_code = 1
167        
168    finally:
169        logger.info(f"Script finished with exit code: {exit_code}")
170        logger.info("=" * 60 + "\n")
171    
172    sys.exit(exit_code)
173
174
175if __name__ == "__main__":
176    main()

How to Run This Script

Windows Task Scheduler Setup

  1. Save the script as C:\Scripts\automation_script.py
  2. Open Task Scheduler
  3. Create Basic Task with these settings:
    • Program: C:\Users\You\AppData\Local\Programs\Python\Python311\python.exe
    • Arguments: "C:\Scripts\automation_script.py"
    • Start in: C:\Scripts

Linux/macOS Cron Setup

bash
1# Edit crontab
2crontab -e
3
4# Add line (runs every day at 8 AM):
50 8 * * * /usr/bin/python3 /home/user/scripts/automation_script.py

Common Issues & Solutions

IssueSolution
Script doesn't runCheck full paths for Python and script
"ModuleNotFoundError"Install packages for the correct Python version
Permission deniedRun as administrator or check file permissions
Script runs but no outputCheck working directory; use absolute paths
Missed schedulesCheck "Run as soon as possible after missed" setting

Taking It Further

Run at System Startup

Windows: Create a .bat file in the Startup folder:

batch
1@echo off
2pythonw.exe "C:\Scripts\my_script.py"

Linux: Add to /etc/rc.local or create a systemd service

Create a Systemd Service (Linux)

ini
1# /etc/systemd/system/my-automation.service
2[Unit]
3Description=My Python Automation
4After=network.target
5
6[Service]
7Type=simple
8User=youruser
9WorkingDirectory=/home/youruser/scripts
10ExecStart=/usr/bin/python3 /home/youruser/scripts/scheduler.py
11Restart=always
12
13[Install]
14WantedBy=multi-user.target

Enable it:

bash
1sudo systemctl enable my-automation
2sudo systemctl start my-automation

Conclusion

Your Python scripts shouldn't need babysitting. With proper scheduling, error handling, and logging, they become truly autonomous tools that work for you around the clock.

Start with one script. Get it running reliably on a schedule. Then expand to more. Before long, you'll have an army of automated processes handling your routine tasks while you focus on work that matters.

True automation runs itself.

Set it and forget it.

Sponsored Content

Interested in advertising? Reach automation professionals through our platform.

Share this article