The Sentry Python SDK (sentry-sdk) works with Python 3.6+ and includes built-in integrations for the most popular frameworks and libraries.
Installation
pip install --upgrade sentry-sdk
Basic initialization
Call sentry_sdk.init() once at startup, before your application begins handling requests.
import sentry_sdk
sentry_sdk.init(
dsn="https://examplePublicKey@o0.ingest.sentry.io/0",
environment="production",
release="my-app@1.0.0",
traces_sample_rate=1.0,
)
Python SDK option names use snake_case (e.g., traces_sample_rate) while JavaScript SDKs use camelCase (e.g., tracesSampleRate). The behavior is identical.
Framework integrations
Django
Flask
FastAPI
Celery
Add DjangoIntegration to your settings.py. The integration automatically captures request data, user information, and database query spans.# settings.py
import sentry_sdk
from sentry_sdk.integrations.django import DjangoIntegration
sentry_sdk.init(
dsn="https://examplePublicKey@o0.ingest.sentry.io/0",
environment="production",
release="my-app@1.0.0",
integrations=[
DjangoIntegration(),
],
traces_sample_rate=1.0,
# Send user information (email, username) with events.
# Disable if your privacy policy prohibits this.
send_default_pii=True,
)
Set send_default_pii=True only if your privacy policy permits sending user identifiers to a third party. When omitted, Sentry strips personally identifiable information from requests.
import sentry_sdk
from sentry_sdk.integrations.flask import FlaskIntegration
from flask import Flask
sentry_sdk.init(
dsn="https://examplePublicKey@o0.ingest.sentry.io/0",
environment="production",
release="my-app@1.0.0",
integrations=[
FlaskIntegration(),
],
traces_sample_rate=1.0,
)
app = Flask(__name__)
Initialize Sentry before creating the Flask app so that the integration can hook into request handling.import sentry_sdk
from sentry_sdk.integrations.fastapi import FastApiIntegration
from sentry_sdk.integrations.starlette import StarletteIntegration
from fastapi import FastAPI
sentry_sdk.init(
dsn="https://examplePublicKey@o0.ingest.sentry.io/0",
environment="production",
release="my-app@1.0.0",
integrations=[
StarletteIntegration(),
FastApiIntegration(),
],
traces_sample_rate=1.0,
)
app = FastAPI()
FastAPI integration requires both StarletteIntegration and FastApiIntegration because FastAPI is built on Starlette.import sentry_sdk
from sentry_sdk.integrations.celery import CeleryIntegration
sentry_sdk.init(
dsn="https://examplePublicKey@o0.ingest.sentry.io/0",
integrations=[
CeleryIntegration(),
],
traces_sample_rate=1.0,
)
Call sentry_sdk.init() in the same module where Celery is configured so it runs in both the worker and the scheduler processes.
Capturing exceptions
Automatic capture
Unhandled exceptions are captured automatically once sentry_sdk.init() is called.
Manual capture
try:
process_payment(order)
except Exception as e:
sentry_sdk.capture_exception(e)
raise
Capture a message
sentry_sdk.capture_message("Inventory count below threshold", level="warning")
Valid levels: "fatal", "error", "warning", "info", "debug".
Setting context
with sentry_sdk.configure_scope() as scope:
scope.set_user({"id": "42", "email": "user@example.com"})
scope.set_tag("section", "checkout")
scope.set_extra("order_id", "12345")
You can also set context for a single event using push_scope:
with sentry_sdk.push_scope() as scope:
scope.set_tag("payment_method", "stripe")
sentry_sdk.capture_exception(e)
Changes made inside push_scope apply only to events captured within that block.
Use start_transaction and start_span to instrument your code:
with sentry_sdk.start_transaction(name="checkout", op="task") as transaction:
with sentry_sdk.start_span(op="db.query", description="SELECT orders") as span:
rows = db.execute("SELECT * FROM orders WHERE id = %s", [order_id])
span.set_data("row_count", len(rows))
with sentry_sdk.start_span(op="http.client", description="POST /payment"):
response = requests.post("https://payment.example.com/charge", json=payload)
The name appears as the transaction name in Sentry’s Performance view. The op field categorizes the span type.
Filtering events with before_send
Return None from before_send to drop an event, or return the modified event to send it:
def before_send(event, hint):
if "exc_info" in hint:
exc_type, exc_value, tb = hint["exc_info"]
# Drop a specific exception type
if isinstance(exc_value, MyIgnoredException):
return None
# Scrub a sensitive header
if event.get("request", {}).get("headers", {}).get("Authorization"):
event["request"]["headers"]["Authorization"] = "[Filtered]"
return event
sentry_sdk.init(
dsn="https://examplePublicKey@o0.ingest.sentry.io/0",
before_send=before_send,
)
Logging integration
Capture Python log records as Sentry breadcrumbs or events:
import logging
import sentry_sdk
from sentry_sdk.integrations.logging import LoggingIntegration
sentry_sdk.init(
dsn="https://examplePublicKey@o0.ingest.sentry.io/0",
integrations=[
LoggingIntegration(
level=logging.INFO, # Capture INFO+ as breadcrumbs
event_level=logging.ERROR, # Send ERROR+ as Sentry events
),
],
)
Avoid setting event_level to logging.WARNING on high-traffic services. Every warning log will become a Sentry event and can exhaust your quota quickly.