{"id":2614,"library":"nats-py","title":"NATS Client for Python","description":"nats-py is an asyncio-based Python client for the NATS messaging system, providing robust support for core NATS features like publish/subscribe, request/reply, and queue groups, as well as advanced functionalities through JetStream, Key-Value, and Microservices. It is actively maintained by NATS.io, with frequent patch and minor releases, ensuring compatibility with the latest NATS server features. The current version is 2.14.0.","status":"active","version":"2.14.0","language":"en","source_language":"en","source_url":"https://github.com/nats-io/nats.py","tags":["nats","messaging","pubsub","asyncio","jetstream","microservices"],"install":[{"cmd":"pip install nats-py","lang":"bash","label":"Core client"},{"cmd":"pip install nats-py[nkeys]","lang":"bash","label":"With NKeys/JWT support (optional)"}],"dependencies":[{"reason":"Required for NATS v2.0 decentralized authentication features using JWTs.","package":"nkeys","optional":true}],"imports":[{"note":"While `from nats.aio.client import Client` is technically possible for advanced usage, `import nats` and using `nats.connect()` is the idiomatic and recommended way to establish a connection for most use cases since v2.0.0.","wrong":"from nats.aio.client import Client as NATS\nnc = await NATS().connect(\"nats://localhost:4222\")","symbol":"nats.connect","correct":"import nats\n\nnc = await nats.connect(\"nats://localhost:4222\")"}],"quickstart":{"code":"import asyncio\nimport nats\nimport os\n\nasync def main():\n    nats_url = os.environ.get(\"NATS_URL\", \"nats://localhost:4222\")\n    try:\n        # Connect to NATS. Use async with for graceful connection management.\n        async with await nats.connect(nats_url) as nc:\n            print(f\"Connected to NATS at {nats_url}\")\n\n            # Simple asynchronous message handler\n            async def message_handler(msg):\n                subject = msg.subject\n                data = msg.data.decode()\n                print(f\"Received on '{subject}': {data}\")\n\n            # Subscribe to a subject\n            sub = await nc.subscribe(\"foo\", cb=message_handler)\n            print(\"Subscribed to 'foo'\")\n\n            # Publish a message\n            await nc.publish(\"foo\", b'Hello NATS from Python!')\n            print(\"Published 'Hello NATS from Python!' to 'foo'\")\n\n            # Wait for a short period to allow message processing\n            await asyncio.sleep(1) \n\n            # Unsubscribe and drain connection\n            await sub.unsubscribe()\n            await nc.drain()\n            print(\"Drained connection and unsubscribed.\")\n\n    except nats.errors.NoServersError:\n        print(f\"Could not connect to NATS at {nats_url}. Is the server running?\")\n    except Exception as e:\n        print(f\"An error occurred: {e}\")\n\nif __name__ == '__main__':\n    # Run the main asynchronous function\n    asyncio.run(main())\n","lang":"python","description":"This quickstart demonstrates how to connect to a NATS server, subscribe to a subject with an asynchronous callback, publish a message, and ensure graceful shutdown using `async with`. Replace `nats://localhost:4222` with your NATS server address or set the `NATS_URL` environment variable."},"warnings":[{"fix":"If you require using keys that do not conform to the new validation rules, pass `validate_keys=False` to the relevant KV methods (e.g., `kv.put(key, value, validate_keys=False)`).","message":"In `v2.11.0`, Key-Value (KV) keys validation became enabled by default. Previously invalid keys might now cause errors unless explicitly opted out.","severity":"breaking","affected_versions":">=2.11.0"},{"fix":"Update imports from `asyncio_nats_client` to `nats`. Adjust code to handle `Subscription` objects for subscriptions and use new error class names. Old style errors are subclasses of new ones, so existing `except` blocks might still catch them.","message":"The library was renamed from `asyncio-nats-client` to `nats-py` in `v2.0.0`. Key API changes include `subscribe()` no longer returning a Subscription ID directly (it returns a `Subscription` object), and error class names were updated to follow PEP-8 conventions (e.g., `ErrSlowConsumer` became `SlowConsumerError`).","severity":"breaking","affected_versions":">=2.0.0"},{"fix":"Ensure all NATS operations are performed within an `async def` function and executed using `asyncio.run(your_async_main_function())` or integrated into an existing `asyncio` event loop. Do not block the event loop with long-running synchronous tasks; offload them if necessary.","message":"`nats-py` is an `asyncio`-native client. All core operations are asynchronous and must be `await`ed within `async def` functions. Attempting to call these directly from synchronous code will result in runtime errors.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Always use `async with await nats.connect(...) as nc:` for robust connection management, or ensure `await nc.close()` (or `await nc.drain()`) is called in a `finally` block or before application exit for explicit connection handling.","message":"Proper connection lifecycle management is crucial. Connections should be explicitly closed or drained, especially when using a `nats.connect()` without `async with`. Use `await nc.close()` or `await nc.drain()` to ensure all pending messages are sent and resources are released gracefully.","severity":"gotcha","affected_versions":"All versions"},{"fix":"If you manage the NATS server, plan server upgrades carefully. Consider a blue/green deployment strategy or a full cluster shutdown/restart if a rolling upgrade is not feasible or causes issues. Consult NATS server documentation for recommended upgrade paths.","message":"The NATS server clustering protocol is incompatible between NATS server v1 and v2. While `nats-py` is compatible with both server versions, a rolling upgrade of a NATS server cluster from v1 to v2 (or vice-versa) can lead to split-brain scenarios and client connection issues during the transition period.","severity":"gotcha","affected_versions":"All versions (server-side concern)"},{"fix":"If your authentication tokens are short-lived, consider updating your `connect` call to pass a callable function to the `token` parameter. This function will be invoked on each connection attempt, including reconnections, to fetch a fresh token.","message":"In `v2.13.0`, the `token` parameter in `nats.connect()` was enhanced to accept a callable, enabling dynamic token refresh on reconnect. If you were previously relying on static token behavior for reconnections, be aware of this new capability.","severity":"gotcha","affected_versions":">=2.13.0"}],"env_vars":null,"last_verified":"2026-04-10T00:00:00.000Z","next_check":"2026-07-09T00:00:00.000Z"}