Python Script Monitoring

Know when your scheduled Python script stops running.

PingCron monitors any Python job — cron-driven, APScheduler, Celery beat, schedule library, or systemd timer. One requests.get() and you get alerted when the job stops checking in.

5 monitors free · No credit card · Live in under 60 seconds

Python scripts fail in ways traceback never tells you about.

A scheduled Python script can stop running for reasons that never produce a traceback you'll see. The virtualenv path changed after a server update. A pip install in production broke a transitive dependency. Cron runs your script with a different PATH and PYTHONPATH than your shell. The .env file you depend on is missing in the cron context.

Sometimes the script does run, but exits early due to a caught exception that just logs a warning and moves on. Or it succeeds 99% of the time and silently fails the 1% — exactly the runs you needed for that customer report.

Without external monitoring, your Python jobs are running on faith. PingCron replaces faith with a missed-check-in alert.

Python scheduling pitfalls:

  • Cron uses a different PATH and PYTHONPATH — virtualenv breaks on next reboot
  • requirements.txt updated but pip install never ran on the cron server
  • Script depends on .env loaded by your shell, but cron has no shell context
  • APScheduler's BackgroundScheduler dies silently when its parent process exits
  • Celery beat scheduler is running but the Redis/RabbitMQ broker isn't reachable
  • Your script catches all exceptions and logs them — but logs go to /dev/null

Setup

One line of Python protects an entire scheduled script.

Drop a requests.get() (or urllib equivalent) at the end of any successful run. PingCron alerts you the moment a check-in is missed.

Before

0 * * * * /usr/bin/python3 /opt/jobs/sync_orders.py

After

0 * * * * /usr/bin/python3 /opt/jobs/sync_orders.py && curl -fsS https://api.pingcron.io/ping/abc123

If you'd rather ping from inside Python (so a partial-success exit code doesn't ping), put the call at the bottom of your script. The cron-level && approach works for most cases.

Real-world examples

Plain Python script with requests

import requests

PING_URL = 'https://api.pingcron.io/ping/abc123'

try:
    sync_orders()
    requests.get(PING_URL, timeout=10)
except Exception as e:
    requests.get(PING_URL + '/fail', timeout=10)
    raise

APScheduler job

from apscheduler.schedulers.blocking import BlockingScheduler
import requests

sched = BlockingScheduler()

@sched.scheduled_job('cron', hour=2)
def nightly_job():
    process_data()
    requests.get('https://api.pingcron.io/ping/abc123')

sched.start()

Celery beat task

from celery import Celery
import requests

app = Celery('tasks')

@app.task
def hourly_sync():
    sync_to_warehouse()
    requests.get('https://api.pingcron.io/ping/abc123')

schedule library

import schedule, time, requests

def run_etl():
    do_etl()
    requests.get('https://api.pingcron.io/ping/abc123')

schedule.every().hour.do(run_etl)

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

Python scheduling patterns we monitor.

Cron-driven scripts, in-process schedulers, distributed task queues.

Cron + Python scripts

The classic pattern: crontab calls a .py file every N minutes.

APScheduler jobs

BlockingScheduler or BackgroundScheduler running in-process.

Celery beat

Distributed task queue with periodic tasks via celerybeat.

schedule library

Lightweight cron alternative used in single-process scripts.

systemd timers

Modern Linux replacement for cron running .service units.

Airflow DAG tasks

Per-task heartbeats from Airflow's PythonOperator.

Long-running Python loops

while True: scripts that need to prove they're still alive.

Data pipeline scripts

pandas/SQL extracts, ML inference jobs, ETL scripts.

How it works

Works with every Python scheduling pattern.

01

Create a Python script monitor

Pick the interval that matches how often the script should run.

02

Add requests.get() at the end of a run

Or hit the URL from cron with curl. If you'd prefer to also ping on failure, wrap the body in try/except and ping /fail in the except block.

03

Optionally instrument start and finish

Hit /start at the beginning and /done at the end if you want PingCron to also catch hung jobs (still running but not finishing on time).

04

Get alerted on missed check-ins

Email, Slack, Discord, or webhook the moment a ping is overdue.

Alerts where you'll actually see them.

Configure as many channels as you want per monitor.

Email

HTML alerts with monitor details and direct links.

Slack

Post to any Slack channel via incoming webhook.

Discord

Native Discord webhook integration.

Custom webhooks

POST alerts to any endpoint with full payload.

FAQ

Two options. From cron: append && curl https://api.pingcron.io/ping/<id> to your cron line — the curl only fires if the script exits 0. From inside Python: import requests and call requests.get(PING_URL) at the end of your script. The Python approach gives you more control over what counts as success.
Yes. Inside any APScheduler-decorated function, call requests.get('https://api.pingcron.io/ping/<id>') after the work completes. APScheduler still controls the scheduling — PingCron is just verifying the job actually ran.
Yes. Inside any Celery task body, send the ping after the task completes. If the task throws, ping /fail in the except handler so you get an instant alert. PingCron complements Celery — Celery handles distribution, PingCron handles "did this actually run on schedule".
Yes. Make sure your cron entry activates the virtualenv first (or uses the absolute path to the venv's python binary), and the requests library is installed in that venv. The PingCron call itself is just an HTTP request — virtualenv-agnostic.
Yes — instrument both /start and the success ping. /start signals the job kicked off; the success ping signals it finished. If the success ping doesn't arrive within your expected runtime + grace period, PingCron knows the script is hung. This catches infinite-loop bugs and deadlocks that pure end-of-run pings miss.
Inside Python is more accurate — it pings only after the meaningful work completes, not just after the Python interpreter exits. If your script catches exceptions and exits 0 even on partial failure, the && approach over-reports success. Inline pinging gives you control over what counts as a successful run.
Yes. 5 monitors free with email, Slack, and Discord alerts. No credit card. Enough for the 5 most critical scheduled jobs in a typical Python codebase.

Related monitoring guides

Stop trusting cron logs to catch Python failures.

One requests.get() at the end of your script. Get alerted the moment a check-in is missed.

Start monitoring free

5 monitors free · No credit card · Live in under 60 seconds