{"id":5758,"library":"connect-python","title":"Connect RPC for Python (Legacy package name)","description":"Connect-Python provides a server and client runtime library for the Connect RPC protocol in Python, supporting all three RPC patterns (unary, server streaming, client streaming, bidirectional streaming) and interoperability with gRPC. Version 0.9.0 is the final release under this package name; future development and updates have transitioned to the 'connectrpc' package. The library is actively maintained under its new name with a focus on stability and feature parity.","status":"deprecated","version":"0.9.0","language":"en","source_language":"en","source_url":"https://github.com/connectrpc/connect-python","tags":["rpc","connectrpc","grpc","protocol-buffers","asgi","client","server"],"install":[{"cmd":"pip install connect-python==0.9.0","lang":"bash","label":"Install specific legacy version"},{"cmd":"pip install connectrpc","lang":"bash","label":"Install current version (recommended)"}],"dependencies":[{"reason":"HTTP client transport, Rust-backed for full Connect protocol support (from v0.8.0)","package":"pyqwest","optional":false},{"reason":"Protocol Buffers for message serialization","package":"protobuf","optional":false},{"reason":"Needed for `protoc` code generation utilities","package":"grpcio-tools","optional":true}],"imports":[{"symbol":"ConnectClient","correct":"from connectrpc.client import ConnectClient"},{"symbol":"ConnectASGI","correct":"from connectrpc.servers.asgi import ConnectASGI"},{"symbol":"ConnectError","correct":"from connectrpc.client import ConnectError"}],"quickstart":{"code":"import asyncio\nfrom connectrpc.client import ConnectClient, ConnectError\nfrom connectrpc.servers.asgi import ConnectASGI\nfrom connectrpc.protocol import Code\nfrom dataclasses import dataclass\n\n# Assume greet_pb2 and greet_connect have been generated from greet.proto:\n# protoc -I. --python_out=. --pyi_out=. --grpc_python_out=. --connect_python_out=. greet.proto\n\n# --- Minimal Proto Definition (conceptual for quickstart) ---\n# syntax = \"proto3\";\n# package greet.v1;\n# message GreetRequest { string name = 1; }\n# message GreetResponse { string greeting = 1; }\n# service GreetService { rpc Greet(GreetRequest) returns (GreetResponse); }\n\n# --- Mock generated classes for quickstart --- \n# In a real app, these would come from `import greet_pb2`, `import greet_connect`\n@dataclass\nclass GreetRequest:\n    name: str\n\n@dataclass\nclass GreetResponse:\n    greeting: str\n\nclass GreetServiceBase:\n    async def greet(self, request: GreetRequest) -> GreetResponse:\n        raise NotImplementedError()\n\nclass GreetServiceAsyncClient:\n    def __init__(self, client: ConnectClient, base_url: str): self._client = client; self._base_url = base_url\n    async def greet(self, request: GreetRequest) -> GreetResponse:\n        response = await self._client.unary(f\"{self._base_url}/greet.v1.GreetService/Greet\", request, GreetResponse)\n        return response\n\n# --- Server Implementation ---\nclass MyGreetService(GreetServiceBase):\n    async def greet(self, request: GreetRequest) -> GreetResponse:\n        print(f\"Server received: {request.name}\")\n        return GreetResponse(greeting=f\"Hello, {request.name}!\")\n\nasync def run_server_and_client():\n    # Setup server\n    server_app = ConnectASGI(services=[MyGreetService()])\n\n    # For this quickstart, we'll simulate a server request handler.\n    # In a real app, you'd run this with uvicorn: `uvicorn server_module:server_app`\n    print(\"\\n--- Running Server (simulated) ---\")\n    async def handle_server_request(path: str, request_data: bytes):\n        # This is a simplified simulation of ASGI handling\n        mock_scope = {\"type\": \"http\", \"method\": \"POST\", \"path\": path, \"headers\": [(b\"content-type\", b\"application/json\")]}\n        mock_receive = asyncio.Queue()\n        await mock_receive.put({\"type\": \"http.request\", \"body\": request_data, \"more_body\": False})\n        mock_send = asyncio.Queue()\n\n        await server_app(mock_scope, mock_receive.get, mock_send.put)\n\n        response_events = []\n        while True:\n            event = await mock_send.get()\n            response_events.append(event)\n            if event[\"type\"] == \"http.response.body\" and not event.get(\"more_body\", False):\n                break\n        \n        status_code = next(e[\"status\"] for e in response_events if e[\"type\"] == \"http.response.start\")\n        body = b\"\".join(e[\"body\"] for e in response_events if e[\"type\"] == \"http.response.body\")\n        return status_code, body\n\n    # Setup client\n    # For this quickstart, we'll use a mocked client that talks directly to the server_app\n    class MockConnectClient(ConnectClient):\n        async def unary(self, path: str, request, response_class):\n            # Serialize request as JSON for simulation\n            import json\n            request_data = json.dumps({\"name\": request.name}).encode('utf-8')\n            \n            status_code, response_body = await handle_server_request(path, request_data)\n\n            if status_code != 200:\n                raise ConnectError(Code(status_code), details=response_body.decode('utf-8'))\n            \n            # Deserialize response from JSON for simulation\n            response_dict = json.loads(response_body.decode('utf-8'))\n            return response_class(greeting=response_dict['greeting'])\n\n    mock_connect_client = MockConnectClient()\n    client = GreetServiceAsyncClient(mock_connect_client, \"/greet.v1.GreetService\")\n\n    # Make a client request\n    print(\"\\n--- Running Client ---\")\n    try:\n        req = GreetRequest(name=\"Alice\")\n        res = await client.greet(req)\n        print(f\"Client received: {res.greeting}\")\n    except ConnectError as e:\n        print(f\"Client error: {e.code} - {e.details}\")\n\nif __name__ == \"__main__\":\n    asyncio.run(run_server_and_client())\n","lang":"python","description":"This quickstart demonstrates a basic unary (request-response) RPC using Connect-Python. It conceptually shows a `GreetService` with a `Greet` method. In a real application, you would first define your service in a `.proto` file (e.g., `greet.proto`), then generate Python code using `protoc` with the Connect-Python plugin. The example simulates a server responding to a client request. For production, the server (`server_app`) would be run with an ASGI server like Uvicorn."},"warnings":[{"fix":"Update your `pip install` commands and `pyproject.toml` (or `requirements.txt`) to depend on `connectrpc` instead of `connect-python` (e.g., `pip install connectrpc`). The import paths within your code (`from connectrpc.client import ...`) remain the same even after renaming the PyPI package.","message":"The `connect-python` PyPI package has been renamed to `connectrpc`. Version `0.9.0` is the LAST release under the `connect-python` name. All future updates, bug fixes, and new features will *only* be published to the `connectrpc` package.","severity":"breaking","affected_versions":">=0.9.0"},{"fix":"Ensure you have a compatible Rust toolchain installed (e.g., via `rustup`) if pre-compiled wheels for `pyqwest` are not available for your system when installing the library.","message":"The library relies on `pyqwest` as its HTTP client transport (introduced in v0.8.0), which is a Rust-backed library. While `pyqwest` provides pre-compiled wheels for most common platforms, users on less common architectures or specific environments might encounter issues requiring a Rust toolchain to build `pyqwest` from source.","severity":"gotcha","affected_versions":">=0.8.0"},{"fix":"For OpenTelemetry instrumentation, explicitly add `connectrpc-otel` to your dependencies and refer to its documentation for usage, rather than expecting built-in OTel support in the core `connectrpc` package.","message":"The `connectrpc-otel` package, providing OpenTelemetry instrumentation, has been released separately (v0.1.0). While not a breaking change for `connect-python` itself, direct OTel integration within the core library may become deprecated in favor of this external package.","severity":"deprecated","affected_versions":">=0.9.0"}],"env_vars":null,"last_verified":"2026-04-14T00:00:00.000Z","next_check":"2026-07-13T00:00:00.000Z"}