{"id":991,"library":"grpclib","title":"grpclib","description":"grpclib is a pure-Python implementation of the gRPC protocol for asyncio, designed to give developers full control over HTTP/2 streams. It allows for building high-performance client and server applications using asynchronous Python. The current version is 0.4.9 and it requires Python 3.10 or newer. The library receives regular updates with bug fixes and new features.","status":"active","version":"0.4.9","language":"python","source_language":"en","source_url":"https://github.com/vmagamedov/grpclib","tags":["grpc","asyncio","networking","rpc","protocol buffers"],"install":[{"cmd":"pip install \"grpclib[protobuf]\"","lang":"bash","label":"Basic installation with Protobuf support"},{"cmd":"pip install grpcio-tools","lang":"bash","label":"For Protocol Buffers code generation"}],"dependencies":[{"reason":"Required at runtime for message serialization/deserialization.","package":"protobuf","optional":false},{"reason":"Required for generating gRPC stub files from .proto definitions (compile-time only).","package":"grpcio-tools","optional":true},{"reason":"Optional, for using Mozilla's collection of CA certificates for secure channels.","package":"certifi","optional":true}],"imports":[{"symbol":"Channel","correct":"from grpclib.client import Channel"},{"symbol":"Server","correct":"from grpclib.server import Server"},{"symbol":"graceful_exit","correct":"from grpclib.utils import graceful_exit"},{"symbol":"Status","correct":"from grpclib import Status"},{"symbol":"GRPCError","correct":"from grpclib import GRPCError"},{"note":"Example of generated client stub import (based on 'helloworld.proto')","symbol":"GreeterStub","correct":"from .helloworld_grpc import GreeterStub"},{"note":"Example of generated server base class import (based on 'helloworld.proto')","symbol":"GreeterBase","correct":"from .helloworld_grpc import GreeterBase"}],"quickstart":{"code":"# 1. Define your service in a .proto file (e.g., helloworld.proto):\n# syntax = \"proto3\";\n# package helloworld;\n# message HelloRequest { string name = 1; }\n# message HelloReply { string message = 1; }\n# service Greeter { rpc SayHello (HelloRequest) returns (HelloReply); }\n\n# 2. Generate Python code from the .proto file:\n# python3 -m grpc_tools.protoc -I. --python_out=. --grpclib_python_out=. helloworld.proto\n\n# 3. Server implementation (server.py)\nimport asyncio\nfrom grpclib.utils import graceful_exit\nfrom grpclib.server import Server\n\n# Generated by protoc from helloworld.proto\nfrom helloworld_pb2 import HelloReply\nfrom helloworld_grpc import GreeterBase\n\nclass Greeter(GreeterBase):\n    async def SayHello(self, stream):\n        request = await stream.recv_message()\n        message = f'Hello, {request.name}!'\n        await stream.send_message(HelloReply(message=message))\n\nasync def main_server(*, host='127.0.0.1', port=50051):\n    server = Server([Greeter()])\n    # Note: graceful_exit isn't supported in Windows\n    with graceful_exit([server]):\n        await server.start(host, port)\n        print(f'Serving on {host}:{port}')\n        await server.wait_closed()\n\n# 4. Client implementation (client.py)\nfrom grpclib.client import Channel\n\n# Generated by protoc from helloworld.proto\nfrom helloworld_pb2 import HelloRequest, HelloReply\nfrom helloworld_grpc import GreeterStub\n\nasync def main_client():\n    async with Channel('127.0.0.1', 50051) as channel:\n        greeter = GreeterStub(channel)\n        reply = await greeter.SayHello(HelloRequest(name='Dr. Strange'))\n        print(reply.message)\n\n# To run the server and then the client:\n# if __name__ == '__main__':\n#    asyncio.run(main_server())\n#    # In another terminal, run:\n#    # asyncio.run(main_client())\n","lang":"python","description":"This quickstart demonstrates how to set up a basic gRPC server and client using `grpclib`. First, define your service in a `.proto` file, then use `protoc` with the `grpclib` plugin to generate Python stubs. Finally, implement your server logic and client calls using the generated stubs."},"warnings":[{"fix":"Ensure your `protobuf` package (`pip install --upgrade protobuf`) and `protoc` compiler (`brew upgrade protobuf` or similar) are up-to-date when upgrading `grpclib`.","message":"Upgrading `grpclib` often requires updating your `protobuf` installation. `grpclib` regenerates its internal protobuf files, which can introduce new minimum `protobuf` runtime version requirements. For example, v0.4.6 required `protobuf>=3.20.0`. Always check the changelog for specific version bumps.","severity":"breaking","affected_versions":">=0.3.x"},{"fix":"Update your `protoc` command to use `--grpclib_python_out` instead of `--python_grpc_out` for generating `grpclib` specific stubs. Example: `python3 -m grpc_tools.protoc -I. --python_out=. --grpclib_python_out=. helloworld.proto`.","message":"The `protoc` plugin option `--python_grpc_out` was renamed to `--grpclib_python_out` in `grpclib` v0.3.2. Build scripts using the old option will fail.","severity":"breaking","affected_versions":"<0.3.2"},{"fix":"Remove the `loop` argument from calls to `Channel`, `Server`, and other public APIs where it was previously accepted. `asyncio.run()` will handle loop management.","message":"The `loop` argument in public APIs (e.g., `Channel`, `Server` constructors) has been deprecated as `asyncio` automatically manages the event loop.","severity":"deprecated","affected_versions":">=0.3.x"},{"fix":"On Windows, implement custom signal handling (e.g., using `asyncio.Event` and `signal.signal` for `SIGINT` on Python 3.8+ if available) or an alternative shutdown mechanism for your `grpclib` server.","message":"The `grpclib.utils.graceful_exit` utility, used for handling server shutdown signals, is not supported on Windows operating systems.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Ensure all metadata keys and values conform to gRPC wire format specifications: keys with `-bin` suffix for binary values (bytes type), and printable ASCII for text values (str type). `grpclib` handles base64 encoding/decoding for `-bin` suffixed values automatically.","message":"In v0.4.0, metadata validation was fixed. This may cause exceptions if your application was previously sending invalid metadata values that did not conform to gRPC specifications (e.g., non-printable ASCII characters for text metadata or improperly encoded binary metadata).","severity":"gotcha","affected_versions":"<0.4.0"},{"fix":"Run the `protoc` compiler with the `grpclib` plugin to generate stubs for your `.proto` files. Example: `python3 -m grpc_tools.protoc -I. --python_out=. --grpclib_python_out=. your_service.proto`. Ensure the generated files are placed in a location discoverable by your Python application (e.g., in the same directory as your Python script or added to `PYTHONPATH`).","message":"Protobuf message and service stubs (e.g., `_pb2.py`, `_grpclib.py`) must be generated from your `.proto` files using the `protoc` compiler and the `grpclib` plugin. If these files are missing or not in the Python path, your application will encounter a `ModuleNotFoundError`.","severity":"breaking","affected_versions":"All versions"}],"env_vars":null,"last_verified":"2026-05-12T22:19:16.987Z","next_check":"2026-06-27T00:00:00.000Z","problems":[{"fix":"On the client, catch `GRPCError` and inspect `error.status` and `error.message` to handle specific gRPC status codes. On the server, raise `GRPCError` with an appropriate `Status` enum value and an optional message to signal specific failures to the client.","cause":"A gRPC call failed, either on the client or server side, due to a protocol error, invalid argument, internal server error, network issue, or explicit cancellation.","error":"grpclib.exceptions.GRPCError"},{"fix":"Ensure both client and server applications handle stream closures gracefully; clients should call `stream.end()` for streaming calls, and servers should handle `asyncio.CancelledError` in request handlers during shutdown. Consider enabling `grpclib` debugging logs for more insights into the HTTP/2 frames.","cause":"The underlying HTTP/2 stream was unexpectedly terminated by the remote party (client or server), often due to a protocol violation, network issue, or a premature shutdown.","error":"StreamTerminatedError: Stream reset by remote party"},{"fix":"Ensure `__init__.py` files exist in all directories forming the Python package structure. Generate the protobuf files using the `protoc` command with correct `-I` (proto import path) and output (`--python_out`, `--grpclib_python_out`) arguments, relative to the root of your Python package. Adjust Python import statements to reflect the correct package structure (e.g., `from . import your_service_pb2`).","cause":"The Python interpreter cannot find the protobuf-generated `_pb2.py` or gRPC stub `_grpc.py` files because they are not in the Python import path, or the `protoc` command was used incorrectly during generation.","error":"ModuleNotFoundError: No module named 'your_service_pb2'"},{"fix":"If you intend to use `grpcio`'s async API, ensure `grpcio` is installed and updated to a version that supports `grpc.aio`. If you are using `grpclib`, use its native asynchronous components like `grpclib.client.Channel` and `grpclib.server.Server` instead of `grpc.aio` constructs.","cause":"This error typically occurs when attempting to use the asynchronous API of the `grpcio` library (`grpc.aio`) while `grpcio` is not installed, is an outdated version, or when `grpclib` is intended for use (which has its own distinct async API).","error":"AttributeError: module 'grpc' has no attribute 'aio'"},{"fix":"This error often points to deeper issues. Review full tracebacks for details. Check for misconfigured proxies, load balancers, or firewalls that might be interfering with HTTP/2 traffic. Ensure `grpclib` versions are compatible across client and server if possible, and that both sides are handling HTTP/2 streams according to the gRPC protocol.","cause":"An underlying HTTP/2 protocol error occurred, indicating a violation of the HTTP/2 specification during communication between the gRPC client and server.","error":"grpclib.exceptions.ProtocolError"}],"ecosystem":"pypi","meta_description":null,"install_score":100,"install_tag":"verified","quickstart_score":null,"quickstart_tag":null,"pypi_latest":"0.4.9","cli_name":"grpclib","install_checks":{"last_tested":"2026-05-12","tag":"verified","tag_description":"installs cleanly on critical runtimes, fast import, recently tested","results":[{"runtime":"python:3.10-alpine","python_version":"3.10","os_libc":"alpine (musl)","variant":"protobuf","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":null,"import_time_s":1.18,"mem_mb":6.2,"disk_size":"22.4M"},{"runtime":"python:3.10-alpine","python_version":"3.10","os_libc":"alpine (musl)","variant":"protobuf","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":1.1,"mem_mb":6.2,"disk_size":"22.4M"},{"runtime":"python:3.10-alpine","python_version":"3.10","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":null,"import_time_s":null,"mem_mb":null,"disk_size":"110.9M"},{"runtime":"python:3.10-alpine","python_version":"3.10","os_libc":"alpine (musl)","variant":"default","exit_code":1,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":null,"mem_mb":null,"disk_size":null},{"runtime":"python:3.10-slim","python_version":"3.10","os_libc":"slim (glibc)","variant":"protobuf","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":2.6,"import_time_s":1.59,"mem_mb":6.2,"disk_size":"24M"},{"runtime":"python:3.10-slim","python_version":"3.10","os_libc":"slim (glibc)","variant":"protobuf","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":1.9,"mem_mb":6.2,"disk_size":"24M"},{"runtime":"python:3.10-slim","python_version":"3.10","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":4.4,"import_time_s":null,"mem_mb":null,"disk_size":"176M"},{"runtime":"python:3.10-slim","python_version":"3.10","os_libc":"slim (glibc)","variant":"default","exit_code":1,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":null,"mem_mb":null,"disk_size":null},{"runtime":"python:3.11-alpine","python_version":"3.11","os_libc":"alpine (musl)","variant":"protobuf","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":null,"import_time_s":0.74,"mem_mb":7.5,"disk_size":"24.4M"},{"runtime":"python:3.11-alpine","python_version":"3.11","os_libc":"alpine (musl)","variant":"protobuf","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.78,"mem_mb":7.5,"disk_size":"24.4M"},{"runtime":"python:3.11-alpine","python_version":"3.11","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":null,"import_time_s":null,"mem_mb":null,"disk_size":"118.0M"},{"runtime":"python:3.11-alpine","python_version":"3.11","os_libc":"alpine (musl)","variant":"default","exit_code":1,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":null,"mem_mb":null,"disk_size":null},{"runtime":"python:3.11-slim","python_version":"3.11","os_libc":"slim (glibc)","variant":"protobuf","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":2.4,"import_time_s":0.61,"mem_mb":7.5,"disk_size":"26M"},{"runtime":"python:3.11-slim","python_version":"3.11","os_libc":"slim (glibc)","variant":"protobuf","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.63,"mem_mb":7.5,"disk_size":"26M"},{"runtime":"python:3.11-slim","python_version":"3.11","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":3.3,"import_time_s":null,"mem_mb":null,"disk_size":"183M"},{"runtime":"python:3.11-slim","python_version":"3.11","os_libc":"slim (glibc)","variant":"default","exit_code":1,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":null,"mem_mb":null,"disk_size":null},{"runtime":"python:3.12-alpine","python_version":"3.12","os_libc":"alpine (musl)","variant":"protobuf","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":null,"import_time_s":0.76,"mem_mb":8.4,"disk_size":"16.3M"},{"runtime":"python:3.12-alpine","python_version":"3.12","os_libc":"alpine (musl)","variant":"protobuf","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.86,"mem_mb":8.4,"disk_size":"16.3M"},{"runtime":"python:3.12-alpine","python_version":"3.12","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":null,"import_time_s":null,"mem_mb":null,"disk_size":"118.6M"},{"runtime":"python:3.12-alpine","python_version":"3.12","os_libc":"alpine (musl)","variant":"default","exit_code":1,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":null,"mem_mb":null,"disk_size":null},{"runtime":"python:3.12-slim","python_version":"3.12","os_libc":"slim (glibc)","variant":"protobuf","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":2.1,"import_time_s":0.77,"mem_mb":8.4,"disk_size":"17M"},{"runtime":"python:3.12-slim","python_version":"3.12","os_libc":"slim (glibc)","variant":"protobuf","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.88,"mem_mb":8.4,"disk_size":"17M"},{"runtime":"python:3.12-slim","python_version":"3.12","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":3.3,"import_time_s":null,"mem_mb":null,"disk_size":"183M"},{"runtime":"python:3.12-slim","python_version":"3.12","os_libc":"slim (glibc)","variant":"default","exit_code":1,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":null,"mem_mb":null,"disk_size":null},{"runtime":"python:3.13-alpine","python_version":"3.13","os_libc":"alpine (musl)","variant":"protobuf","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":null,"import_time_s":0.76,"mem_mb":8.9,"disk_size":"16.0M"},{"runtime":"python:3.13-alpine","python_version":"3.13","os_libc":"alpine (musl)","variant":"protobuf","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.78,"mem_mb":8.9,"disk_size":"15.9M"},{"runtime":"python:3.13-alpine","python_version":"3.13","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":null,"import_time_s":null,"mem_mb":null,"disk_size":"115.2M"},{"runtime":"python:3.13-alpine","python_version":"3.13","os_libc":"alpine (musl)","variant":"default","exit_code":1,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":null,"mem_mb":null,"disk_size":null},{"runtime":"python:3.13-slim","python_version":"3.13","os_libc":"slim (glibc)","variant":"protobuf","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":2.1,"import_time_s":0.75,"mem_mb":8.9,"disk_size":"17M"},{"runtime":"python:3.13-slim","python_version":"3.13","os_libc":"slim (glibc)","variant":"protobuf","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.83,"mem_mb":8.9,"disk_size":"17M"},{"runtime":"python:3.13-slim","python_version":"3.13","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":3.5,"import_time_s":null,"mem_mb":null,"disk_size":"182M"},{"runtime":"python:3.13-slim","python_version":"3.13","os_libc":"slim (glibc)","variant":"default","exit_code":1,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":null,"mem_mb":null,"disk_size":null},{"runtime":"python:3.9-alpine","python_version":"3.9","os_libc":"alpine (musl)","variant":"protobuf","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":null,"import_time_s":0.16,"mem_mb":6.1,"disk_size":"21.6M"},{"runtime":"python:3.9-alpine","python_version":"3.9","os_libc":"alpine (musl)","variant":"protobuf","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.17,"mem_mb":6.1,"disk_size":"21.6M"},{"runtime":"python:3.9-alpine","python_version":"3.9","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":null,"import_time_s":null,"mem_mb":null,"disk_size":"110.1M"},{"runtime":"python:3.9-alpine","python_version":"3.9","os_libc":"alpine (musl)","variant":"default","exit_code":1,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":null,"mem_mb":null,"disk_size":null},{"runtime":"python:3.9-slim","python_version":"3.9","os_libc":"slim (glibc)","variant":"protobuf","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":3.2,"import_time_s":0.14,"mem_mb":6.1,"disk_size":"23M"},{"runtime":"python:3.9-slim","python_version":"3.9","os_libc":"slim (glibc)","variant":"protobuf","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.15,"mem_mb":6.1,"disk_size":"23M"},{"runtime":"python:3.9-slim","python_version":"3.9","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":5,"import_time_s":null,"mem_mb":null,"disk_size":"175M"},{"runtime":"python:3.9-slim","python_version":"3.9","os_libc":"slim (glibc)","variant":"default","exit_code":1,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":null,"mem_mb":null,"disk_size":null}]},"quickstart_checks":{"last_tested":"2026-04-24","tag":null,"tag_description":null,"results":[{"runtime":"python:3.10-alpine","exit_code":1},{"runtime":"python:3.10-slim","exit_code":1},{"runtime":"python:3.11-alpine","exit_code":1},{"runtime":"python:3.11-slim","exit_code":1},{"runtime":"python:3.12-alpine","exit_code":1},{"runtime":"python:3.12-slim","exit_code":1},{"runtime":"python:3.13-alpine","exit_code":1},{"runtime":"python:3.13-slim","exit_code":1},{"runtime":"python:3.9-alpine","exit_code":1},{"runtime":"python:3.9-slim","exit_code":1}]}}