{"library":"grpc-interceptor","title":"gRPC Interceptor","description":"grpc-interceptor is a Python library that simplifies the implementation of gRPC interceptors. It provides base classes and utility interceptors that offer direct access to request, response, and service context objects, which are typically harder to access with standard `grpc` library interceptors. The library emphasizes a small, readable codebase and minimal dependencies, primarily `grpcio`. It is actively maintained with regular minor releases, currently at version 0.15.4.","language":"python","status":"active","last_verified":"Wed May 20","install":{"commands":["pip install grpc-interceptor","pip install grpc-interceptor[testing]"],"cli":null},"imports":["from grpc_interceptor import ServerInterceptor","from grpc_interceptor import AsyncServerInterceptor","from grpc_interceptor import ClientInterceptor","from grpc_interceptor import ExceptionToStatusInterceptor","from grpc_interceptor import AsyncExceptionToStatusInterceptor","from grpc_interceptor.exceptions import GrpcException","from grpc_interceptor.exceptions import NotFound"],"auth":{"required":false,"env_vars":[]},"quickstart":{"code":"import grpc\nfrom concurrent import futures\nfrom grpc_interceptor import ServerInterceptor\nfrom grpc_interceptor.exceptions import GrpcException, NotFound\n\n# Assuming a generated protobuf service like my_pb2_grpc and my_pb2\n# For demonstration, we'll mock these:\nclass MockRequest:\n    def __init__(self, name):\n        self.name = name\nclass MockResponse:\n    def __init__(self, message):\n        self.message = message\nclass MockServicerContext:\n    def __init__(self):\n        self.code = grpc.StatusCode.OK\n        self.details = ''\n    def set_code(self, code):\n        self.code = code\n    def set_details(self, details):\n        self.details = details\n    def abort(self, code, details):\n        self.set_code(code)\n        self.set_details(details)\n        raise GrpcException(code, details)\n\nclass CustomExceptionInterceptor(ServerInterceptor):\n    def intercept(self, method, request, context, method_name):\n        try:\n            return method(request, context)\n        except GrpcException as e:\n            context.set_code(e.status_code)\n            context.set_details(e.details)\n            raise # Re-raise to let gRPC handle it after context is set\n        except Exception as e:\n            # Catch other unexpected exceptions\n            context.set_code(grpc.StatusCode.INTERNAL)\n            context.set_details(f\"An unexpected error occurred: {e}\")\n            raise\n\nclass MyServiceServicer:\n    def SayHello(self, request, context):\n        if request.name == \"Error\":\n            raise NotFound(\"Name not found!\")\n        return MockResponse(message=f\"Hello, {request.name}!\")\n\ndef serve():\n    # In a real application, you'd use generated stubs and an actual gRPC server\n    interceptors = [CustomExceptionInterceptor()]\n    server = grpc.server(futures.ThreadPoolExecutor(max_workers=10), interceptors=interceptors)\n    \n    # In a real app, you'd add your service here:\n    # my_pb2_grpc.add_MyServiceServicer_to_server(MyServiceServicer(), server)\n    \n    # For this example, we'll simulate the service call through the interceptor\n    service_instance = MyServiceServicer()\n    print(\"Simulating RPC calls through the interceptor:\")\n\n    # Successful call\n    req_success = MockRequest(\"World\")\n    ctx_success = MockServicerContext()\n    try:\n        res_success = interceptors[0].intercept(service_instance.SayHello, req_success, ctx_success, \"/MyService/SayHello\")\n        print(f\"Success: {res_success.message} (Status: {ctx_success.code.name})\")\n    except Exception as e:\n        print(f\"Unexpected error in successful call: {e}\")\n\n    # Error call\n    req_error = MockRequest(\"Error\")\n    ctx_error = MockServicerContext()\n    try:\n        interceptors[0].intercept(service_instance.SayHello, req_error, ctx_error, \"/MyService/SayHello\")\n    except GrpcException as e:\n        print(f\"Caught expected error: {ctx_error.details} (Status: {ctx_error.code.name})\")\n    except Exception as e:\n        print(f\"Caught unexpected error type: {e}\")\n\nif __name__ == '__main__':\n    serve()\n","lang":"python","description":"This quickstart demonstrates how to create a custom server interceptor using `grpc-interceptor` to handle exceptions and set gRPC status codes. It includes a basic `ServerInterceptor` subclass that catches `GrpcException` (like `NotFound`) and maps them to gRPC status codes. The example simulates a gRPC call flow to show both successful and error handling paths.","tag":null,"tag_description":null,"last_tested":"2026-04-24","results":[{"runtime":"python:3.10-alpine","exit_code":0},{"runtime":"python:3.10-slim","exit_code":0},{"runtime":"python:3.11-alpine","exit_code":0},{"runtime":"python:3.11-slim","exit_code":0},{"runtime":"python:3.12-alpine","exit_code":0},{"runtime":"python:3.12-slim","exit_code":0},{"runtime":"python:3.13-alpine","exit_code":0},{"runtime":"python:3.13-slim","exit_code":0},{"runtime":"python:3.9-alpine","exit_code":0},{"runtime":"python:3.9-slim","exit_code":0}]},"compatibility":{"tag":"verified","tag_description":"installs cleanly on critical runtimes, fast import, recently tested","last_tested":"2026-05-20","installed_version":"0.15.4","pypi_latest":"0.15.4","is_stale":false,"summary":{"python_range":"3.10–3.9","success_rate":100,"avg_install_s":2.7,"avg_import_s":0.27,"wheel_type":"wheel"},"results":[{"runtime":"python:3.10-alpine","python_version":"3.10","os_libc":"alpine (musl)","variant":"grpc-interceptor","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"clean","install_time_s":null,"import_time_s":0.14,"mem_mb":5.6,"disk_size":"38.4M"},{"runtime":"python:3.10-alpine","python_version":"3.10","os_libc":"alpine (musl)","variant":"grpc-interceptor","exit_code":0,"wheel_type":null,"failure_reason":null,"import_side_effects":null,"install_time_s":null,"import_time_s":0.14,"mem_mb":5.6,"disk_size":"38.4M"},{"runtime":"python:3.10-alpine","python_version":"3.10","os_libc":"alpine (musl)","variant":"testing","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"clean","install_time_s":null,"import_time_s":0.14,"mem_mb":5.6,"disk_size":"40.1M"},{"runtime":"python:3.10-alpine","python_version":"3.10","os_libc":"alpine (musl)","variant":"testing","exit_code":0,"wheel_type":null,"failure_reason":null,"import_side_effects":null,"install_time_s":null,"import_time_s":0.14,"mem_mb":5.6,"disk_size":"40.1M"},{"runtime":"python:3.10-slim","python_version":"3.10","os_libc":"slim (glibc)","variant":"grpc-interceptor","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"clean","install_time_s":2.9,"import_time_s":0.1,"mem_mb":5.6,"disk_size":"36M"},{"runtime":"python:3.10-slim","python_version":"3.10","os_libc":"slim (glibc)","variant":"grpc-interceptor","exit_code":0,"wheel_type":null,"failure_reason":null,"import_side_effects":null,"install_time_s":null,"import_time_s":0.1,"mem_mb":5.6,"disk_size":"36M"},{"runtime":"python:3.10-slim","python_version":"3.10","os_libc":"slim (glibc)","variant":"testing","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"clean","install_time_s":3.2,"import_time_s":0.1,"mem_mb":5.6,"disk_size":"38M"},{"runtime":"python:3.10-slim","python_version":"3.10","os_libc":"slim (glibc)","variant":"testing","exit_code":0,"wheel_type":null,"failure_reason":null,"import_side_effects":null,"install_time_s":null,"import_time_s":0.1,"mem_mb":5.6,"disk_size":"38M"},{"runtime":"python:3.11-alpine","python_version":"3.11","os_libc":"alpine (musl)","variant":"grpc-interceptor","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"clean","install_time_s":null,"import_time_s":0.22,"mem_mb":6.9,"disk_size":"40.5M"},{"runtime":"python:3.11-alpine","python_version":"3.11","os_libc":"alpine (musl)","variant":"grpc-interceptor","exit_code":0,"wheel_type":null,"failure_reason":null,"import_side_effects":null,"install_time_s":null,"import_time_s":0.25,"mem_mb":6.9,"disk_size":"40.5M"},{"runtime":"python:3.11-alpine","python_version":"3.11","os_libc":"alpine (musl)","variant":"testing","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"clean","install_time_s":null,"import_time_s":0.23,"mem_mb":6.9,"disk_size":"42.6M"},{"runtime":"python:3.11-alpine","python_version":"3.11","os_libc":"alpine (musl)","variant":"testing","exit_code":0,"wheel_type":null,"failure_reason":null,"import_side_effects":null,"install_time_s":null,"import_time_s":0.25,"mem_mb":6.9,"disk_size":"42.6M"},{"runtime":"python:3.11-slim","python_version":"3.11","os_libc":"slim (glibc)","variant":"grpc-interceptor","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"clean","install_time_s":2.4,"import_time_s":0.2,"mem_mb":6.9,"disk_size":"38M"},{"runtime":"python:3.11-slim","python_version":"3.11","os_libc":"slim (glibc)","variant":"grpc-interceptor","exit_code":0,"wheel_type":null,"failure_reason":null,"import_side_effects":null,"install_time_s":null,"import_time_s":0.2,"mem_mb":6.9,"disk_size":"38M"},{"runtime":"python:3.11-slim","python_version":"3.11","os_libc":"slim (glibc)","variant":"testing","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"clean","install_time_s":2.8,"import_time_s":0.2,"mem_mb":6.9,"disk_size":"41M"},{"runtime":"python:3.11-slim","python_version":"3.11","os_libc":"slim (glibc)","variant":"testing","exit_code":0,"wheel_type":null,"failure_reason":null,"import_side_effects":null,"install_time_s":null,"import_time_s":0.2,"mem_mb":6.9,"disk_size":"41M"},{"runtime":"python:3.12-alpine","python_version":"3.12","os_libc":"alpine (musl)","variant":"grpc-interceptor","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"clean","install_time_s":null,"import_time_s":0.45,"mem_mb":8.7,"disk_size":"32.3M"},{"runtime":"python:3.12-alpine","python_version":"3.12","os_libc":"alpine (musl)","variant":"grpc-interceptor","exit_code":0,"wheel_type":null,"failure_reason":null,"import_side_effects":null,"install_time_s":null,"import_time_s":0.48,"mem_mb":8.7,"disk_size":"32.3M"},{"runtime":"python:3.12-alpine","python_version":"3.12","os_libc":"alpine (musl)","variant":"testing","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"clean","install_time_s":null,"import_time_s":0.47,"mem_mb":8.7,"disk_size":"34.4M"},{"runtime":"python:3.12-alpine","python_version":"3.12","os_libc":"alpine (musl)","variant":"testing","exit_code":0,"wheel_type":null,"failure_reason":null,"import_side_effects":null,"install_time_s":null,"import_time_s":0.49,"mem_mb":8.7,"disk_size":"34.4M"},{"runtime":"python:3.12-slim","python_version":"3.12","os_libc":"slim (glibc)","variant":"grpc-interceptor","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"clean","install_time_s":2,"import_time_s":0.41,"mem_mb":8.7,"disk_size":"30M"},{"runtime":"python:3.12-slim","python_version":"3.12","os_libc":"slim (glibc)","variant":"grpc-interceptor","exit_code":0,"wheel_type":null,"failure_reason":null,"import_side_effects":null,"install_time_s":null,"import_time_s":0.46,"mem_mb":8.7,"disk_size":"30M"},{"runtime":"python:3.12-slim","python_version":"3.12","os_libc":"slim (glibc)","variant":"testing","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"clean","install_time_s":2.4,"import_time_s":0.42,"mem_mb":8.7,"disk_size":"32M"},{"runtime":"python:3.12-slim","python_version":"3.12","os_libc":"slim (glibc)","variant":"testing","exit_code":0,"wheel_type":null,"failure_reason":null,"import_side_effects":null,"install_time_s":null,"import_time_s":0.43,"mem_mb":8.7,"disk_size":"32M"},{"runtime":"python:3.13-alpine","python_version":"3.13","os_libc":"alpine (musl)","variant":"grpc-interceptor","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"clean","install_time_s":null,"import_time_s":0.45,"mem_mb":9.2,"disk_size":"32.1M"},{"runtime":"python:3.13-alpine","python_version":"3.13","os_libc":"alpine (musl)","variant":"grpc-interceptor","exit_code":0,"wheel_type":null,"failure_reason":null,"import_side_effects":null,"install_time_s":null,"import_time_s":0.47,"mem_mb":9.2,"disk_size":"31.9M"},{"runtime":"python:3.13-alpine","python_version":"3.13","os_libc":"alpine (musl)","variant":"testing","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"clean","install_time_s":null,"import_time_s":0.46,"mem_mb":9.2,"disk_size":"34.2M"},{"runtime":"python:3.13-alpine","python_version":"3.13","os_libc":"alpine (musl)","variant":"testing","exit_code":0,"wheel_type":null,"failure_reason":null,"import_side_effects":null,"install_time_s":null,"import_time_s":0.49,"mem_mb":9.2,"disk_size":"34.1M"},{"runtime":"python:3.13-slim","python_version":"3.13","os_libc":"slim (glibc)","variant":"grpc-interceptor","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"clean","install_time_s":2.1,"import_time_s":0.43,"mem_mb":9.2,"disk_size":"30M"},{"runtime":"python:3.13-slim","python_version":"3.13","os_libc":"slim (glibc)","variant":"grpc-interceptor","exit_code":0,"wheel_type":null,"failure_reason":null,"import_side_effects":null,"install_time_s":null,"import_time_s":0.48,"mem_mb":9.2,"disk_size":"29M"},{"runtime":"python:3.13-slim","python_version":"3.13","os_libc":"slim (glibc)","variant":"testing","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"clean","install_time_s":2.4,"import_time_s":0.41,"mem_mb":9.2,"disk_size":"32M"},{"runtime":"python:3.13-slim","python_version":"3.13","os_libc":"slim (glibc)","variant":"testing","exit_code":0,"wheel_type":null,"failure_reason":null,"import_side_effects":null,"install_time_s":null,"import_time_s":0.46,"mem_mb":9.2,"disk_size":"32M"},{"runtime":"python:3.9-alpine","python_version":"3.9","os_libc":"alpine (musl)","variant":"grpc-interceptor","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"clean","install_time_s":null,"import_time_s":0.12,"mem_mb":5.7,"disk_size":"37.9M"},{"runtime":"python:3.9-alpine","python_version":"3.9","os_libc":"alpine (musl)","variant":"grpc-interceptor","exit_code":0,"wheel_type":null,"failure_reason":null,"import_side_effects":null,"install_time_s":null,"import_time_s":0.14,"mem_mb":5.7,"disk_size":"37.9M"},{"runtime":"python:3.9-alpine","python_version":"3.9","os_libc":"alpine (musl)","variant":"testing","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"clean","install_time_s":null,"import_time_s":0.13,"mem_mb":5.7,"disk_size":"39.6M"},{"runtime":"python:3.9-alpine","python_version":"3.9","os_libc":"alpine (musl)","variant":"testing","exit_code":0,"wheel_type":null,"failure_reason":null,"import_side_effects":null,"install_time_s":null,"import_time_s":0.14,"mem_mb":5.7,"disk_size":"39.6M"},{"runtime":"python:3.9-slim","python_version":"3.9","os_libc":"slim (glibc)","variant":"grpc-interceptor","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"clean","install_time_s":3.2,"import_time_s":0.13,"mem_mb":5.7,"disk_size":"35M"},{"runtime":"python:3.9-slim","python_version":"3.9","os_libc":"slim (glibc)","variant":"grpc-interceptor","exit_code":0,"wheel_type":null,"failure_reason":null,"import_side_effects":null,"install_time_s":null,"import_time_s":0.13,"mem_mb":5.7,"disk_size":"35M"},{"runtime":"python:3.9-slim","python_version":"3.9","os_libc":"slim (glibc)","variant":"testing","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"clean","install_time_s":3.8,"import_time_s":0.14,"mem_mb":5.7,"disk_size":"37M"},{"runtime":"python:3.9-slim","python_version":"3.9","os_libc":"slim (glibc)","variant":"testing","exit_code":0,"wheel_type":null,"failure_reason":null,"import_side_effects":null,"install_time_s":null,"import_time_s":0.13,"mem_mb":5.7,"disk_size":"37M"}]}}