Keep your Python bots alive with a zero-config, production-ready background web server.
Project description
StayPresent
A lightweight Python package designed to keep your bots and background scripts alive by running a dedicated Flask web server alongside your main application.
Perfect for deploying on platforms like Render, Railway, Koyeb, Heroku, or any host that requires an active HTTP port to keep your service running.
🚀 Features
- Zero-Friction Setup: Get running with just one line of code.
- Production-Ready by Default: Automatically detects and uses
waitressto avoid Flask's "development server" warnings. - Auto-Restarts & Crash Recovery: Automatically respawns your bot process if it crashes, complete with customizable delays and max-restart limits.
- Flexible Responses: Serve custom plain text, JSON (default), or full HTML templates.
- Static Asset Serving: Automatically serves CSS, JS, and images located next to your HTML templates.
- Advanced Control: Easily pass custom command-line arguments and environment variables directly to your bot process.
- Fail-Safe Logging: Logs a clear error if the underlying web server dies unexpectedly.
📦 Installation
Install via pip:
pip install staypresent
Recommended for Production:
To automatically use a production WSGI server and suppress Flask development warnings, install the prod extra. This pulls in waitress.
pip install staypresent[prod]
(Note: If waitress isn't installed, StayPresent gracefully falls back to Flask's built-in development server and logs a one-time warning.)
💻 Usage Guide
Basic Usage (Text Response)
import staypresent
staypresent.web.text("Made With ❤️")
staypresent.run("bot.py")
*Navigating to http://localhost:8080 will return plain text: Made With ❤️*
Note: If you don't configure a response, StayPresent defaults to a JSON response of
{"message": "I'm Present"}at the root/route.
JSON Response
A safe copy of your dictionary is stored. If you need to update live data, just call staypresent.web.json() again.
import staypresent
staypresent.web.json({
"status": "online",
"developer": "John",
"message": "Made With Love ❤️"
})
staypresent.run("bot.py")
HTML Response (with Static Files)
Serve a full HTML page. The file is read fresh on every request, allowing you to edit your HTML on disk without restarting your bot.
import staypresent
# The path is validated immediately and will raise a FileNotFoundError if missing
staypresent.web.html("template/index.html")
staypresent.run("bot.py")
Serving Static Assets: Any files (CSS, JS, images) in the same directory as your HTML file are automatically served. Path traversal is strictly blocked for security.
<!-- template/index.html -->
<!DOCTYPE html>
<html>
<head>
<title>My Bot</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<h1>I'm alive!</h1>
<img src="images/logo.png">
</body>
</html>
Custom Host, Port, and Threads (Complete Example)
import staypresent
staypresent.web.json({
"status": "Running",
"version": "1.0.0"
})
staypresent.run(
"bot.py",
host="0.0.0.0",
port=8080,
threads=8 # Increase if receiving real web traffic
)
⚙️ API Reference
staypresent.run(...)
Launch your bot script alongside the web server.
| Parameter | Type | Default | Description |
|---|---|---|---|
bot_file |
str |
Required | Path to the Python script to run alongside the server. |
host |
str |
"0.0.0.0" |
Host to bind the web server to. |
port |
int |
8080 |
Port to bind the web server to. |
production |
bool |
True |
Uses waitress if installed. Set to False to force the Flask dev server. |
threads |
int |
4 |
Number of worker threads for waitress. Increase this if serving real web traffic rather than just keep-alive pings. (Requires production=True and waitress). |
restart_on_crash |
bool |
True |
Relaunch the bot process if it exits with a non-zero exit code. |
max_restarts |
int |
5 |
Maximum restart attempts after a crash before giving up. |
restart_delay |
float |
2.0 |
Seconds to wait before relaunching the bot process after a crash. |
restart_reset_after |
float |
60.0 |
Seconds the bot must stay alive to reset the consecutive crash counter back to 0. |
bot_args |
list |
None |
Extra command-line arguments to pass to bot_file (e.g., ["--verbose"]). |
env |
dict |
None |
Extra environment variables for the bot process. Merges over the current environment. |
Crash Recovery Details
StayPresent automatically monitors your bot process. If it exits with a non-zero exit code, StayPresent restarts it based on your configuration:
- Clean Exits: An exit code of
0is considered intentional and will not trigger a restart. - Manual Shutdowns: Stopping StayPresent via
Ctrl+C(SIGINT) orSIGTERMshuts down both the server and the bot cleanly. - Smart Counters: The
max_restartslimit applies to consecutive crashes. If your bot runs successfully for the duration ofrestart_reset_after(default 60 seconds), the crash counter resets.
Built-in Health Check
A dedicated /health endpoint is automatically exposed, returning {"status": "ok"}. This is incredibly useful for platform pingers and uptime monitors that require a dedicated health-check path separate from your root / response.
🛠 Requirements
- Python 3.8+
- Flask
waitress(optional, but highly recommended for production)
💡 Use Cases
- Discord & Telegram Bots
- Background Workers & Automation Scripts
- Keeping deployments alive on Render, Railway, Koyeb, and Heroku
License: MIT License
Made with ❤️ using Python.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file staypresent-1.2.0.tar.gz.
File metadata
- Download URL: staypresent-1.2.0.tar.gz
- Upload date:
- Size: 12.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9a3518b0b19b42e640e71b2875277101c88f0f3b07a350e16eb7a3d0de58a315
|
|
| MD5 |
0f102ed5264c608af6ed27bf8d707131
|
|
| BLAKE2b-256 |
d6e7f6128075ed136f78724462fa6e744bee9aa363cf5e1c1d09307a6fd73b5a
|
Provenance
The following attestation bundles were made for staypresent-1.2.0.tar.gz:
Publisher:
python-publish.yml on NTDevLops/StayPresent
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
staypresent-1.2.0.tar.gz -
Subject digest:
9a3518b0b19b42e640e71b2875277101c88f0f3b07a350e16eb7a3d0de58a315 - Sigstore transparency entry: 2207173162
- Sigstore integration time:
-
Permalink:
NTDevLops/StayPresent@caf919cde046be27aae0c190b841e70536b809bd -
Branch / Tag:
refs/heads/main - Owner: https://github.com/NTDevLops
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
python-publish.yml@caf919cde046be27aae0c190b841e70536b809bd -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file staypresent-1.2.0-py3-none-any.whl.
File metadata
- Download URL: staypresent-1.2.0-py3-none-any.whl
- Upload date:
- Size: 10.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1735cab880fecf01e1cbd4353b04cf6200d0ec15a6fa15937b464745fe5851b3
|
|
| MD5 |
c95533b4f3f4f4828e93968386376ec7
|
|
| BLAKE2b-256 |
2e074643c13d222ae7580b4c489d04681ddcab8ccb1fd27bf4dc79a9b732dd90
|
Provenance
The following attestation bundles were made for staypresent-1.2.0-py3-none-any.whl:
Publisher:
python-publish.yml on NTDevLops/StayPresent
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
staypresent-1.2.0-py3-none-any.whl -
Subject digest:
1735cab880fecf01e1cbd4353b04cf6200d0ec15a6fa15937b464745fe5851b3 - Sigstore transparency entry: 2207173167
- Sigstore integration time:
-
Permalink:
NTDevLops/StayPresent@caf919cde046be27aae0c190b841e70536b809bd -
Branch / Tag:
refs/heads/main - Owner: https://github.com/NTDevLops
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
python-publish.yml@caf919cde046be27aae0c190b841e70536b809bd -
Trigger Event:
workflow_dispatch
-
Statement type: