{"id":29979462,"url":"https://github.com/Unleash/unleash-python-sdk","last_synced_at":"2025-08-04T13:04:00.548Z","repository":{"id":37735093,"uuid":"154826150","full_name":"Unleash/unleash-python-sdk","owner":"Unleash","description":"Unleash client SDK for Python 💡💡💡","archived":false,"fork":false,"pushed_at":"2025-08-01T09:07:15.000Z","size":7062,"stargazers_count":88,"open_issues_count":8,"forks_count":63,"subscribers_count":6,"default_branch":"main","last_synced_at":"2025-08-01T11:48:08.781Z","etag":null,"topics":["client-library","feature-flags","feature-management","feature-toggles","hacktoberfest","unleash","unleash-server"],"latest_commit_sha":null,"homepage":"http://unleash.github.io/unleash-client-python","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Unleash.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE.md","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2018-10-26T11:47:02.000Z","updated_at":"2025-07-31T14:10:19.000Z","dependencies_parsed_at":"2023-02-09T12:01:37.037Z","dependency_job_id":"99831173-d42f-4a92-8ab5-ef2769e2ec91","html_url":"https://github.com/Unleash/unleash-python-sdk","commit_stats":{"total_commits":211,"total_committers":27,"mean_commits":7.814814814814815,"dds":"0.37914691943127965","last_synced_commit":"8172750c034610cd97056a73c4b107897e373bc3"},"previous_names":["unleash/unleash-python-sdk"],"tags_count":62,"template":false,"template_full_name":null,"purl":"pkg:github/Unleash/unleash-python-sdk","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Unleash%2Funleash-python-sdk","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Unleash%2Funleash-python-sdk/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Unleash%2Funleash-python-sdk/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Unleash%2Funleash-python-sdk/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Unleash","download_url":"https://codeload.github.com/Unleash/unleash-python-sdk/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Unleash%2Funleash-python-sdk/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":268699205,"owners_count":24292425,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-04T02:00:09.867Z","response_time":79,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["client-library","feature-flags","feature-management","feature-toggles","hacktoberfest","unleash","unleash-server"],"created_at":"2025-08-04T13:02:41.684Z","updated_at":"2025-08-04T13:04:00.527Z","avatar_url":"https://github.com/Unleash.png","language":"Python","funding_links":[],"categories":["Python"],"sub_categories":[],"readme":"# Unleash SDK for Python\n\n![](https://github.com/unleash/unleash-python-sdk/workflows/CI/badge.svg?branch=main) [![Coverage Status](https://coveralls.io/repos/github/Unleash/unleash-python-sdk/badge.svg?branch=main)](https://coveralls.io/github/Unleash/unleash-python-sdk?branch=main) [![PyPI version](https://badge.fury.io/py/UnleashClient.svg)](https://badge.fury.io/py/UnleashClient) ![PyPI - Python Version](https://img.shields.io/pypi/pyversions/UnleashClient.svg) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n\nUnleash is a private, secure, and scalable [feature management platform](https://www.getunleash.io/) built to reduce the risk of releasing new features and accelerate software development. This server-side Python SDK is designed to help you integrate with Unleash and evaluate feature flags inside your application.\n\nYou can use this client with [Unleash Enterprise](https://www.getunleash.io/pricing?utm_source=readme\u0026utm_medium=python) or [Unleash Open Source](https://github.com/Unleash/unleash).\n\n\u003e  **Migrating to v6**\n\u003e\n\u003e If you use custom strategies or access the `features` property on the Unleash Client, read the complete [migration guide](./v6_MIGRATION_GUIDE.md) before upgrading to v6.\n\n\n## Getting Started\n\n### Install the Unleash Client in your project\n\n```bash\npip install UnleashClient\n```\n\n### Initialization\n\nYou must initialize the SDK before you use it. Note that until the SDK has synchronized with the API, all features will evaluate to `false` unless\nyou have a [bootstrapped configuration](#bootstrap) or you use [fallbacks](#fallback-function).\n\n```python\nfrom UnleashClient import UnleashClient\n\nclient = UnleashClient(\n    url=\"https:\u003cYOUR-API-URL\u003e\",\n    app_name=\"my-python-app\",\n    custom_headers={'Authorization': '\u003cAPI token\u003e'})\n\nclient.initialize_client()\n```\n\n### Check features\n\nOnce the SDK is initialized, you can evaluate toggles using the `is_enabled` or `get_variant` methods.\n\n```python\nenabled = client.is_enabled(\"my_toggle\")\nprint(enabled)\n\u003e True\n\nvariant = client.get_variant(\"variant_toggle\")\nprint(variant)\n\u003e {\n\u003e    \"name\": \"variant1\",\n\u003e    \"payload\": {\n\u003e        \"type\": \"string\",\n\u003e        \"value\": \"val1\"\n\u003e        },\n\u003e    \"enabled\": True\n\u003e }\n\n```\n\n### Shutdown\n\nIf your program no longer needs the SDK, you can call `destroy()`, which shuts down the SDK and flushes any pending metrics to Unleash.\n\n```python\nclient.destroy()\n```\n\n## Usage\n\n### Context\n\nBoth the `is_enabled` and `get_variant` functions support [Unleash contexts](https://docs.getunleash.io/reference/unleash-context) as the second parameter.\n\n``` python\napp_context = {\n    \"userId\": \"test@email.com\",\n    \"sessionId\": \"55845\",\n    \"properties\": {\n        \"custom-property\": \"some-value\"\n    }\n}\n\nclient.is_enabled(\"user_id_toggle\", app_context)\nclient.get_variant(\"variant_toggle\", app_context)\n```\n\nThe context values can be any type that has a `__str__` implementation. Types that are explicitly supported are:\n\n- Numerics\n- Strings\n- Dates\n- UUIDs\n\n**Note**: Gradual rollout strategies require you to pass either a `userId` or a `sessionId` for [stickiness](https://docs.getunleash.io/reference/stickiness) to work correctly.\n\n### Fallback function\n\nYou can specify a fallback function for cases where the client doesn't recognize the toggle by using the `fallback_function` keyword argument:\n\n```python\ndef custom_fallback(feature_name: str, context: dict) -\u003e bool:\n    return True\n\nclient.is_enabled(\"my_toggle\", fallback_function=custom_fallback)\n```\n\nThe fallback function **must** accept the feature name and context as positional arguments in that order.\n\nThe client will evaluate the fallback function if the feature flag is not found or an exception occurs when calling the `is_enabled()` method.\n\n### Configuration options\n\nThe UnleashClient constructor supports the following configuration options:\n\n| Parameter \t            | Description\t                                                                                                                                    | Default                   |\n| ------------ \t            | ------------                      \t                                                                                                            | ------------              |\n| url \t                    | URL of your Unleash server. E.g. `https://app.unleash-hosted.com/demo/api/` Required.                                                             | None                      |\n| app_name \t                | Name of the application using the client. Required.\t                                                                                            | None                      |\n| environment               | Logical environment name (deprecated).\t                                                                                                        | \"default\"                 |\n| instance_id               | Unique identifier for this client instance.\t                                                                                                    | \"unleash-client-python\"   |\n| refresh_interval  \t    | How often to fetch feature flags (seconds).\t                                                                                                    | 15                        |\n| refresh_jitter            | Jitter to add to refresh interval (seconds).\t                                                                                                    | None                      |\n| metrics_interval  \t    | How often to send metrics to Unleash (seconds).\t                                                                                                | 60                        |\n| metrics_jitter            | Jitter to add to metrics interval (seconds).\t                                                                                                    | None                      |\n| disable_metrics           | Disable sending usage metrics.\t                                                                                                                | False                     |\n| disable_registration      | Disable client registration.\t                                                                                                                    | False                     |\n| custom_headers            | Additional HTTP headers (e.g. Authorization).\t                                                                                                    | None                      |\n| custom_options            | Extra options for [HTTP requests](https://requests.readthedocs.io/en/latest/api/#main-interface).                                                 | None                      |\n| request_timeout           | HTTP request timeout (seconds).\t                                                                                                                | 30                        |\n| request_retries           | HTTP request retry count.\t                                                                                                                        | 3                         |\n| custom_strategies \t    | Dict of `{name: strategy}` for custom activation strategies. See [custom strategies](#custom-strategies) for more information.                      | None                      |\n| cache_directory \t        | Location for the on-disk cache. Auto-determined.                                                                                                  | None                      |\n| cache \t                | Custom cache implementation (must extend BaseCache). See [custom cache](#custom-cache) for more information                                       | BaseCache                 |\n| scheduler \t            | Custom APScheduler instance.\tAuto-created.                                                                                                       | BaseScheduler             |\n| verbose_log_level \t    | Python logging level for debugging feature flag failures. See https://docs.python.org/3/library/logging.html#logging-levels for more information.\t| 30                        |\n| scheduler_executor \t    | APScheduler executor name to use.\t                                                                                                                | None                      |\n| multiple_instance_mode    | How to handle multiple client instances (BLOCK, WARN, SILENTLY_ALLOW).\t                                                                        | WARN                      |\n| event_callback \t        | Function to handle impression events. See [impression data](#impression-data) for more information.                                               | None                      |\n\n### Bootstrap\n\nBy default, the Python SDK fetches your feature flags from the Unleash API at startup. If you want to make your SDK more resilient (e.g., during network outages), you can bootstrap the client with a local or remote toggle config.\n\nHow it works:\n\n- Use a FileCache (or your own BaseCache implementation).\n\n- Pre-seed it with feature flags using bootstrap_from_dict, bootstrap_from_file, or bootstrap_from_url.\n\n- Pass your cache to the UnleashClient on startup.\n\nThe default FileCache has built-in methods for bootstrapping from a dictionary, file, or URL.\n\n#### Bootstrap from dict\n\n```python\nfrom UnleashClient.cache import FileCache\nfrom UnleashClient import UnleashClient\n\n# Create and seed the cache\ncache = FileCache(\"MY_CACHE\")\ncache.bootstrap_from_dict({\n    \"version\": 2,\n    \"features\": [\n        {\n            \"name\": \"my_toggle\",\n            \"enabled\": True,\n            \"strategies\": [{\"name\": \"default\"}],\n        }\n    ]\n})\n\nclient = UnleashClient(\n    url=\"https://YOUR-API-URL\",\n    app_name=\"my-python-app\",\n    cache=cache\n)\n\n```\n\n#### Bootstrap from file\n\n```python\nfrom pathlib import Path\nfrom UnleashClient.cache import FileCache\n\ncache = FileCache(\"MY_CACHE\")\ncache.bootstrap_from_file(Path(\"/path/to/your_bootstrap.json\"))\n\nclient = UnleashClient(\n    url=\"https://YOUR-API-URL\",\n    app_name=\"my-python-app\",\n    cache=cache\n)\n```\n\n#### Bootstrap from URL\n\n```python\nfrom UnleashClient.cache import FileCache\n\ncache = FileCache(\"MY_CACHE\")\ncache.bootstrap_from_url(\"https://your-server/bootstrap.json\")\n\nclient = UnleashClient(\n    url=\"https://YOUR-API-URL\",\n    app_name=\"my-python-app\",\n    cache=cache\n)\n\n```\n\n### Custom strategies\n\nThe Python SDK lets you define [custom activation strategies](https://docs.getunleash.io/reference/custom-activation-strategies) if the built-in ones don’t cover your needs. This gives you more fine grained control over how your features evaluate.\n\nA custom strategy is just a class that implements an apply method.\n\n``` python\n\nclass ActiveForEmailStrategy:\n    def apply(self, parameters: dict, context: dict = None) -\u003e bool:\n        # Decide if the feature is active for this context\n        return context.get(\"email\") in parameters\n\n```\n\nOnce you’ve defined your strategy, register it when you initialize the client. The key must match the strategy name in Unleash exactly.\n\n``` python\n## You should have a custom strategy defined in Unleash called 'EmailStrategy'\nmy_custom_strategies = {\n    \"EmailStrategy\": ActiveForEmailStrategy()\n}\n\nclient = UnleashClient(\n\n    url=\"https://YOUR-API-URL\",\n    app_name=\"my-python-app\",\n    custom_headers={'Authorization': '\u003cAPI token\u003e'},\n    custom_strategies = my_custom_strategies\n)\n\n```\n\n### Events and impression data\n\nThe Python SDK lets you tap into its behavior through [impression data](https://docs.getunleash.io/reference/impression-data) and lifecycle events.\n\n**Note**: The SDK does not include a built-in event bus — you’ll need to provide your own. The example below shows how to use [Blinker](https://pypi.org/project/blinker/) to send signals.\n\n#### Impression events\n\nTo use impression data:\n- Enable impression data on your feature flags in the Unleash UI.\n- Provide an event_callback function when you initialize the client.\n\nYour callback must accept a single UnleashEvent. You can log it, store it, or send it to another system.\n\n```python\nfrom blinker import signal\nfrom UnleashClient import UnleashClient\nfrom UnleashClient.events import UnleashEvent\n\nsend_data = signal('send-data')\n\n@send_data.connect\ndef receive_data(sender, **kw):\n    print(\"Caught signal from %r, data %r\" % (sender, kw))\n\ndef example_callback(event: UnleashEvent):\n    send_data.send('anonymous', data=event)\n\nclient = UnleashClient(\n    url=\"https://YOUR-API-URL\",\n    app_name=\"my-python-app\",\n    custom_headers={'Authorization': '\u003cAPI token\u003e'},\n    event_callback=example_callback\n)\nclient.initialize_client()\nclient.is_enabled(\"testFlag\")\n\n```\n\nImpression callbacks run in-process — keep them fast to avoid blocking your app.\n\n#### Lifecycle events\n\nThe same event_callback also delivers lifecycle events:\n- FETCHED: triggered when a new version of feature flags is pulled from the Unleash server. (Does not trigger on 304 Not Modified). The FETCHED event includes a features property containing all the feature flags returned by that fetch.\n- READY: triggered once when the SDK first loads feature flags from the Unleash server or a local backup.\n\n```python\nfrom blinker import signal\nfrom UnleashClient import UnleashClient\nfrom UnleashClient.events import UnleashEvent, UnleashEventType\n\nsend_data = signal('send-data')\n\n@send_data.connect\ndef receive_data(sender, **kw):\n    if kw[\"data\"].event_type == UnleashEventType.READY:\n        print(\"SDK is ready: toggles loaded from Unleash or backup\")\n    elif kw[\"data\"].event_type == UnleashEventType.FETCHED:\n        # Only FETCHED events have a 'features' property\n        print(\"Fetched new feature flags:\", kw[\"data\"].features)\n\ndef example_callback(event: UnleashEvent):\n    send_data.send('anonymous', data=event)\n\nclient = UnleashClient(\n    url=\"https://YOUR-API-URL\",\n    app_name=\"my-python-app\",\n    custom_headers={'Authorization': '\u003cAPI token\u003e'},\n    event_callback=example_callback\n)\nclient.initialize_client()\nclient.is_enabled(\"testFlag\")\n\n```\n\n### Custom cache\n\nBy default, the Python SDK stores feature flags in an on-disk cache using fcache. If you need a different storage backend, for example, Redis, memory-only, or a custom database, you can provide your own cache implementation.\n\nBelow is an example custom CustomCache using fcache under the hood.\n\n```python\nfrom typing import Optional, Any\nfrom UnleashClient.cache import BaseCache\nfrom fcache.cache import FileCache as _FileCache\n\nclass CustomCache(BaseCache):\n    # This is specific for FileCache.  Depending on the cache you're using, this may look different!\n    def __init__(self, name: str, directory: Optional[str] = None):\n        self._cache = _FileCache(name, app_cache_dir=directory)\n\n    def set(self, key: str, value: Any):\n        self._cache[key] = value\n        self._cache.sync()\n\n    def mset(self, data: dict):\n        self._cache.update(data)\n        self._cache.sync()\n\n    def get(self, key: str, default: Optional[Any] = None):\n        return self._cache.get(key, default)\n\n    def exists(self, key: str):\n        return key in self._cache\n\n    def destroy(self):\n        return self._cache.delete()\n```\nPass your cache instance to the client with the cache argument:\n\n```python\nclient = UnleashClient(\n    url=\"https://YOUR-API-URL\",\n    app_name=\"my-python-app\",\n    cache=CustomCache(\"my-cache\")\n)\n```\n\n## Running in multi-process setups\n\nThe Python SDK runs a background thread to keep feature flags in sync with the Unleash server. Some runtime environments, like WSGI servers and Celery workers, need extra setup to make sure the SDK works correctly.\n\n### WSGI\n\nWhen using WSGI servers (e.g., for Flask or Django apps), be aware that:\n\n- Many WSGI setups disable threading by default. The SDK needs threads to poll for updates in the background.\n- Make sure to set `enable-threads` in your WSGI config.\n\nWhen running under uWSGI with multiple processes (using the `--processes` option), you may need to enable the `lazy-apps` option. This ensures each process gets a fresh SDK instance.\n\nSee [The Art of Graceful Reloading](https://uwsgi-docs.readthedocs.io/en/latest/articles/TheArtOfGracefulReloading.html#preforking-vs-lazy-apps-vs-lazy) for more details.\n\n### Celery\n\nWhen using the SDK in Celery tasks, make sure you initialize it inside the worker_process_init event. Otherwise, the worker may run but won’t poll for feature flag updates.\n\n```python\nfrom UnleashClient import UnleashClient\nfrom celery.signals import worker_process_init\n\nclient = UnleashClient(\n    url=\"https://YOUR-API-URL\",\n    app_name=\"my-python-app\",\n    custom_headers={'Authorization': '\u003cAPI token\u003e'}\n)\n\n@worker_process_init.connect\ndef configure_workers(sender=None, conf=None, **kwargs):\n    client.initialize_client()\n```\n\n## Contributing and development\n\nWe love community input! If you’d like to report a bug, propose a feature, or improve the SDK, please read our [contribution guide](CONTRIBUTING.md) for how to get started.\n\nFor instructions on setting up your development environment, running tests, and publishing, see our [development documentation](DEVELOPMENT.md).\n\n## License\n\nThis project is [MIT licensed](https://opensource.org/licenses/MIT).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FUnleash%2Funleash-python-sdk","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FUnleash%2Funleash-python-sdk","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FUnleash%2Funleash-python-sdk/lists"}