Monitor Python scripts: a try/except and one HTTP request
Ping on success. Report the exception on failure. Let absence
detection catch everything that never reaches your
except: the OOM kill, the crashed interpreter, the cron
entry that vanished. No SDK, no agent; requests or plain
stdlib. Free, no monitor cap.
Your assistant can do this for you
Monitor my Python scripts with LastPing
On this page
The snippets
Create a monitor in the console (its schedule = how often the script should run, plus a grace window), copy the ping URL, and wrap your entry point.
With requests
Success pings the monitor URL; an exception POSTs its text to
/fail (stored with the ping, 10,000 bytes max) and
re-raises so the process still exits non-zero:
import requests
PING = "https://ping.lastping.dev/<your-monitor-id>"
def main() -> None:
... # your job
if __name__ == "__main__":
try:
main()
except Exception as exc:
requests.post(f"{PING}/fail", data=str(exc)[:10000], timeout=10)
raise
else:
requests.get(PING, timeout=10)
Standard library only
Zero dependencies: urllib.request sends a GET for
success and a POST (a Request with a body) for
failure:
from urllib.request import Request, urlopen
PING = "https://ping.lastping.dev/<your-monitor-id>"
def main() -> None:
... # your job
if __name__ == "__main__":
try:
main()
except Exception as exc:
urlopen(Request(f"{PING}/fail", data=str(exc)[:10000].encode()), timeout=10)
raise
else:
urlopen(PING, timeout=10)
Optional: overrun detection and run duration
A /start ping arms the hung-job alarm (no success
inside the grace window → incident), and a shared
rid pairs start with finish so each run's duration
is recorded:
import time
import requests
PING = "https://ping.lastping.dev/<your-monitor-id>"
def main() -> None:
... # your job
if __name__ == "__main__":
rid = str(int(time.time()))
requests.get(f"{PING}/start", params={"rid": rid}, timeout=10)
try:
main()
except Exception as exc:
requests.post(f"{PING}/fail", data=str(exc)[:10000], timeout=10)
raise
else:
requests.get(PING, params={"rid": rid}, timeout=10)
Why the re-raise matters
raise keeps the exit code non-zero, so whatever
runs the script (cron,
systemd, a
Kubernetes CronJob) still
sees the failure and applies its own retry semantics. The ping
adds alerting; it never hides the error.
What this catches
The except reports what it can; the silence reports the
rest.
- An exception: the
/failping opens an incident immediately, with the exception text stored on the ping. - A crash your code never sees: OOM kill, segfault in a C extension,
kill -9. No success ping arrives; the grace window raises the alert. - The script never ran: missing cron entry, broken virtualenv path, dead host. Absence → incident.
- A hung run: with the
/startping armed, a job stuck on a lock or a dead socket opens an incident inside the grace window. - Recovery: the next successful run closes the incident and sends a recovery notice automatically.
Questions people ask
Front-loaded answers: the most important fact first.
-
How do I monitor a Python cron job?
Wrap the entry point in try/except: on success,
requests.getthe monitor URLhttps://ping.lastping.dev/<your-monitor-id>; on exception,requests.postthe error text to the/failendpoint and re-raise so the exit code stays non-zero. If the script fails, hangs, or never starts, LastPing alerts you by email, Slack, Discord, Telegram, ntfy, Pushover, Microsoft Teams, Google Chat or webhook. -
Do I need a special library or SDK?
No. A ping is one plain HTTP request: GET, HEAD, or POST.
requestsis convenient; the standard library'surllib.requestworks with zero dependencies. -
What if my script crashes before it can ping?
That's the point of dead-man's-switch monitoring: a script that segfaults, is OOM-killed, or never starts sends no ping, and the missing ping itself opens the incident after the grace window. The failure path needs no working code.
-
Can I see the exception in the alert trail?
Yes. POST the exception text as the body of the
/failping. Up to 10,000 bytes are stored with the ping event and retrievable via the API. -
Does this work outside plain scripts?
Anywhere Python runs and can make an HTTP request: a Django management command, a task in a worker, an ETL step, a notebook job. The ping doesn't care what invoked the code.
-
Is Python job monitoring free?
Yes. LastPing is free for individuals with no monitor cap. See how it compares to Healthchecks.io and Cronitor.
Your except clause can't catch a missing process.
Six lines now beat a quiet data gap later. First alert wired up in about a minute, and LastPing monitors itself the same way.