# Sentry Python: init first, sample deliberately, verify from a file

## Install and init

```
pip install sentry-sdk
```

Call `sentry_sdk.init()` as early as possible in your app's entry point, before importing modules that could throw during import. In async programs, init inside the first async function so async code gets instrumented properly:

```python
import sentry_sdk

sentry_sdk.init(
    dsn="___PUBLIC_DSN___",
    send_default_pii=True,  # adds request headers and IP; opt in consciously
    traces_sample_rate=0.1,  # NOT 1.0 in production (see below)
    # release defaults to the SENTRY_RELEASE env var, else the git SHA
)
```

## The sample-rate trap

The docs example uses `traces_sample_rate=1.0` because it is a getting-started snippet. At 1.0 every transaction becomes a billed span. In production start low (0.05-0.2) and watch usage, or use `traces_sampler` for dynamic per-request decisions (it must return a float between 0 and 1, and returning 0 filters the transaction out). Note the semantics: `traces_sample_rate=0` means no new traces start, but `traces_sample_rate=None` (the default) disables tracing entirely, including continuing incoming traces.

## Verify from a file, not a REPL

Errors raised in an interactive shell like IPython do not trigger error monitoring. Verify with a script file:

```python
# verify_sentry.py
import sentry_sdk
sentry_sdk.init(dsn="___PUBLIC_DSN___")
1 / 0
```

Run it, then check the issue stream. If nothing arrives, turn on `debug=True` in init to see SDK diagnostics in stderr, and confirm the DSN matches your project's DSN exactly (wrong project or org slug means events get rejected).

## Shutdown behavior

The SDK sends from a background queue with `shutdown_timeout` defaulting to 2 seconds. Short-lived scripts and CLI tools can lose the last events; call `sentry_sdk.flush()` before exit in those cases.