Skip to main content

Finally, an alert when your code is done

Project description

Finalert

Finally, an alert when your code is done.

Finalert sends progress, completion, and failure notifications for Python jobs. Its tqdm integration can notify you at selected percentages, while Telegram, PushPlus personal WeChat, SMTP email, and generic JSON webhooks provide flexible delivery. The core package has no third-party runtime dependencies; tqdm support is optional.

  1. Use notify() at the end of an existing script for the simplest integration:
from finalert import notify

run_analysis()
save_results()

notify("The analysis results have been saved.")
  1. Use watch() when you also want failure notifications and elapsed time:
from finalert import watch

with watch("Model training"):
    train_model()
    save_model()
  1. Install the tqdm integration and add milestone notifications to an existing

progress loop:

python -m pip install "finalert[tqdm]"
from finalert import watch
from finalert.tqdm import tqdm

with watch("Model training"):
    for batch in tqdm(
        batches,
        desc="Model training",
        notify_at=(25, 50, 75),
    ):
        train_batch(batch)

This sends progress messages at 25%, 50%, and 75%, followed by one final success or failure notification.

Features

  • Send a notification from the final line of a Python program.
  • Report successful completion, failure, elapsed time, and an exception summary.
  • Deliver notifications through Telegram, PushPlus personal WeChat, SMTP email, or a JSON webhook.
  • Preserve the original program result if notification delivery fails.
  • Configure credentials through environment variables.
  • Send low-frequency tqdm progress notifications at selected percentages.

Installation

Install from PyPI:

python -m pip install finalert

Install the optional tqdm integration with:

python -m pip install "finalert[tqdm]"

Confirm the installation:

finalert --version

Configuration

Finalert reads configuration from environment variables. Select one provider by setting FINALERT_PROVIDER to telegram, pushplus, email, or webhook.

Finalert does not automatically load .env files. If you keep the variables in a shell file such as .finalert.env, load it before running a job:

source .finalert.env

Do not commit tokens or passwords to version control. Add .finalert.env to .gitignore and restrict its permissions with chmod 600 .finalert.env.

Telegram

Create a bot with Telegram's @BotFather, send the bot at least one message, and obtain the bot token and destination chat ID to compete the following in the .finalert.env file:

export FINALERT_PROVIDER="telegram"
export FINALERT_TELEGRAM_TOKEN="your-bot-token"
export FINALERT_TELEGRAM_CHAT_ID="your-chat-id"

For a complete walkthrough, see the Telegram setup guide.

Personal WeChat through PushPlus

PushPlus is an independent third-party notification service that can deliver Finalert messages through its WeChat channel. Create a PushPlus account, complete the identity verification required by PushPlus for its send API, connect the WeChat recipient, and obtain a personal message token.

PushPlus fee notice: PushPlus registration is separate from the identity verification required to send messages. According to the current PushPlus documentation, identity verification has a service fee. These are third-party requirements and may change, so review the current PushPlus verification terms before choosing this provider.

export FINALERT_PROVIDER="pushplus"
export FINALERT_PUSHPLUS_TOKEN="your-message-token"

Then verify delivery:

finalert test --provider pushplus

Finalert sends the token in the HTTPS request body and validates the PushPlus response code. Treat the token as a password and never commit it to Git.

For a complete walkthrough, see the PushPlus setup guide.

SMTP email

The following example uses STARTTLS on port 587:

export FINALERT_PROVIDER="email"
export FINALERT_SMTP_HOST="smtp.example.com"
export FINALERT_SMTP_PORT="587"
export FINALERT_SMTP_USERNAME="sender@example.com"
export FINALERT_SMTP_PASSWORD="your-app-password"
export FINALERT_EMAIL_TO="receiver@example.com"

Separate multiple recipients with commas:

export FINALERT_EMAIL_TO="first@example.com,second@example.com"

If the sender address differs from the SMTP username, set it explicitly:

export FINALERT_EMAIL_FROM="notifications@example.com"

For implicit SMTP SSL, commonly used on port 465:

export FINALERT_SMTP_PORT="465"
export FINALERT_SMTP_SSL="true"
export FINALERT_SMTP_STARTTLS="false"

JSON webhook

export FINALERT_PROVIDER="webhook"
export FINALERT_WEBHOOK_URL="https://example.com/hooks/finalert"

Finalert sends an HTTP POST request with a JSON body:

{
  "title": "✅ analysis.py completed",
  "message": "The analysis results have been saved."
}

Optional HTTP headers can be supplied as a JSON object:

export FINALERT_WEBHOOK_HEADERS='{"Authorization":"Bearer secret"}'

Network timeout

All providers use a 10-second timeout by default. Override it when needed:

export FINALERT_TIMEOUT="5"

Test the configuration

Send a test notification using the configured provider:

finalert test

Override FINALERT_PROVIDER for one test while still reading that provider's credentials from the environment:

finalert test --provider telegram

A successful request prints:

✓ Test notification sent

Usage

Notify at the end of a script

from finalert import notify

perform_analysis()

notify("Results were written to output.csv")

Customize the notification title:

notify(
    "Results were written to output.csv",
    title="Daily analysis completed",
)

If no arguments are provided, Finalert uses the current script name:

notify()

notify() returns True when the provider accepts the notification and False when configuration or delivery fails:

if not notify("The export has completed"):
    print("The job succeeded, but its notification could not be sent.")

Delivery errors are logged as warnings. They do not turn a successful job into a failed job. A final-line notify() call only runs if program execution reaches that line, so it cannot report an earlier crash; use watch() instead.

Monitor success and failure

Wrap a block with watch() to report either outcome:

from finalert import watch

with watch("Dataset export"):
    build_dataset()
    export_dataset()

On success, the notification includes elapsed time. On failure, it includes elapsed time plus the exception type and message. Finalert then re-raises the original exception so the program keeps its normal failure behaviour.

Override the provider in Python

You may store credentials for multiple providers in .finalert.env. When no provider is specified in Python, FINALERT_PROVIDER selects the default provider. A call-level provider= argument overrides that default for the individual call:

notify("Backup complete", provider="email")

with watch("Model training", provider="telegram"):
    train_model()

The selected provider's credentials still come from environment variables. The order of provider credentials in .finalert.env has no effect, and each notification is sent through one provider only.

Report tqdm progress milestones

Install the optional integration and import Finalert's tqdm wrapper:

python -m pip install "finalert[tqdm]"
from finalert.tqdm import tqdm

for item in tqdm(
    dataset,
    desc="Dataset processing",
    notify_at=(25, 50, 75, 100),
):
    process(item)

Each percentage is notified at most once. If one update crosses several milestones, Finalert sends only the latest milestone by default to avoid a burst of messages. Use catch_up="all" to send every crossed milestone.

Combine progress milestones with watch() for a final success or failure notification:

from finalert import watch
from finalert.tqdm import tqdm

with watch("Dataset processing"):
    for item in tqdm(
        dataset,
        desc="Dataset processing",
        notify_at=(25, 50, 75),
    ):
        process(item)

Percentage notifications require an iterable with a known length or an explicit total=.... It also supports manual progress updates and trange shortcut. For complete options and behaviour, see the tqdm integration guide.

Limitations

  • Finalert cannot notify event that prevents Python from executing notification code.
  • Finalert sends notifications synchronously and does not retry failures.
  • Finalert does not automatically read .env or other configuration files.
  • tqdm percentage notifications require a known positive total.
  • PushPlus is a third-party service, so availability and delivery limits are controlled by PushPlus and WeChat.

Development

Run the test suite after installing the package with its tqdm extra:

python -m pip install -e ".[tqdm]"
python -m unittest discover -s tests -v

The tests mock external services and do not send real Telegram, PushPlus, email, or webhook requests. Use finalert test with real credentials for an integration check.

Project layout

src/finalert/           Package source
src/finalert/providers/ Notification providers
src/finalert/tqdm.py    Optional tqdm integration
tests/                 Unit tests
tqdm.md                tqdm integration guide
pushplus.md            PushPlus personal WeChat guide
dist/                  Built wheel

License

Finalert is distributed under the MIT License. See LICENSE for details.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

finalert-0.3.1.tar.gz (24.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

finalert-0.3.1-py3-none-any.whl (16.0 kB view details)

Uploaded Python 3

File details

Details for the file finalert-0.3.1.tar.gz.

File metadata

  • Download URL: finalert-0.3.1.tar.gz
  • Upload date:
  • Size: 24.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.11

File hashes

Hashes for finalert-0.3.1.tar.gz
Algorithm Hash digest
SHA256 4e7ad2b62f2e8068702ba19de900e4a400523636bdde6692add28ea6d887c175
MD5 ba6d7b05c743c15aa76780fd6f7fdbef
BLAKE2b-256 f22b96ac59bc9bf5482c680221d91912c7d4a0c17e4c882165aaced15e0d5cfd

See more details on using hashes here.

File details

Details for the file finalert-0.3.1-py3-none-any.whl.

File metadata

  • Download URL: finalert-0.3.1-py3-none-any.whl
  • Upload date:
  • Size: 16.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.11

File hashes

Hashes for finalert-0.3.1-py3-none-any.whl
Algorithm Hash digest
SHA256 d9eae74bf146a85b8a0ef3625f9b1bbb5f1b07424eb4d5d57abcd54c0e3990b6
MD5 5d98af643838d4a5f4136d73456edc74
BLAKE2b-256 ece07fc85e4c48977cc7785300981a1f2e4571c2c13cefe80bc76a65e7762252

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page