Python SDK

switchbox-flags — constructor, methods, and configuration.

The Python SDK is published to PyPI as switchbox-flags and imported as switchbox. It has zero runtime dependencies (Python stdlib only) and is thread-safe.

pip install switchbox-flags

The same reference ships in the package README on PyPI.

Switchbox(...)

from switchbox import Switchbox
client = Switchbox(
sdk_key="your-sdk-key", # required
poll_interval=10, # seconds between background refreshes
on_error=None, # callback(exc) on fetch/parse failure
timeout=10, # per-fetch HTTP timeout, seconds
block_on_init=True, # fetch the first config synchronously
telemetry=True, # anonymous usage telemetry (see below)
on_evaluation=None, # callback(flag_key, value, user) per evaluation
cdn_base_url=None, # override the CDN host (advanced)
)

Creates a client. By default (block_on_init=True) it performs an initial synchronous fetch on construction — client.ready is True on return — then starts a background daemon thread that refreshes the config every poll_interval seconds. Set block_on_init=False to return immediately and fetch in the background instead (checks fall back to your defaults until ready). Create one client at startup and reuse it.

Background refreshes are conditional requests: the SDK sends back the ETag the edge gave it, so a poll that finds nothing changed returns an empty 304 with no config body. Steady-state polling transfers almost nothing, whatever the size of your config. This is automatic, with nothing to configure.

ParameterTypeDefaultDescription
sdk_keystrThe environment's SDK key from the dashboard.
poll_intervalint10Seconds between background config refreshes.
on_errorCallable[[Exception], None] | NoneNoneInvoked when a fetch or parse fails (the client keeps serving the last good config), or when your on_evaluation hook raises.
timeoutint10HTTP timeout for each fetch, in seconds.
block_on_initboolTrueFetch the first config synchronously (client ready on return). False fetches in the background.
telemetryboolTrueAnonymous usage telemetry (see below). False disables it.
on_evaluationCallable[[str, Any, dict | None], None] | NoneNoneCalled after every evaluation with (flag_key, value, user). See Measure in your own analytics.
cdn_base_urlstr | NoneNoneOverride the CDN base URL. Defaults to the Switchbox edge; you rarely need this.

client.ready

if client.ready:
...

A property — True once a config has been loaded at least once. Useful to gate startup logic on the first successful fetch.

client.enabled(flag_key, user=None)

client.enabled("new_checkout", user={"user_id": "42"}) # -> bool

Returns whether a boolean flag is enabled for the user. Returns False if the flag doesn't exist or no config has loaded — a safe default.

ParameterTypeDescription
flag_keystrThe flag key to evaluate.
userdict | NoneUser context for targeting and rollouts.

client.get_value(flag_key, user=None, default=None)

client.get_value("search_algorithm", user={"user_id": "42"}, default="v1")

Returns the resolved value of a string, number, or JSON flag (a json flag comes back as a parsed object/array). Returns default if the flag doesn't exist or no config is available.

ParameterTypeDescription
flag_keystrThe flag key to evaluate.
userdict | NoneUser context for targeting and rollouts.
defaultAnyReturned when the flag is absent or unresolved.

client.get_all_flags(user=None)

client.get_all_flags(user={"user_id": "42"})
# {"dark_mode": True, "search_algorithm": "v2", "max_results": 50}

Returns every flag resolved for the user, as a dict. Empty dict if no config is available.

client.close()

client.close()

Stops the background polling thread. Call it on application shutdown.

Context manager

Switchbox supports with, which calls close() automatically:

with Switchbox(sdk_key="your-sdk-key") as client:
if client.enabled("new_checkout", user={"user_id": "42"}):
show_new_checkout()

The on_evaluation hook

def on_evaluation(flag_key, value, user):
... # forward the exposure to your analytics
client = Switchbox(sdk_key="your-sdk-key", on_evaluation=on_evaluation)

Called after every enabled() and get_value() call with the flag key, the resolved value, and the user context you passed in. It is fire-and-forget: an exception inside your handler never breaks the flag check (it is reported through on_error), and the hook carries no evaluation logic. Ready-made handlers for common analytics tools are in Measure in your own analytics.

Anonymous usage telemetry

The SDK reports anonymous aggregate usage from a background thread — per-flag evaluation counts and value distribution, with no identity, no user context, and no cookies — which powers the dashboard's flag usage panel. On by default; pass telemetry=False to disable it. Exactly what is sent and shown is documented in Connection & usage.

Offline behaviour

If the CDN is unreachable, the SDK keeps serving the last successfully fetched config — your flags keep working. If it has never fetched a config (e.g. the network was down at startup), enabled() returns False and get_value() returns your default. No exceptions are raised into your call path; failures go to on_error if you supplied it.

Next