You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

stubgen配合mypy-protobuf使用时泛型报错的修复方法

问题场景

当结合protoc使用mypy-protobuf提供的protoc-gen-mypy插件搭配protoc,为gRPC Greeter服务生成mypy类型存根时,会遇到泛型相关的类型检查错误。

用于生成greeter_pb2_grpc.pyi文件的执行命令如下:

python -m grpc_tools.protoc --plugin=protoc-gen-mypy=`which protoc-gen-mypy` -Iprotos --mypy_grpc_out=grpc protos/greeter.proto

生成的greeter_pb2_grpc.pyi文件内容如下:

"""
@generated by mypy-protobuf.  Do not edit manually!
isort:skip_file
"""
import abc
import greeter_pb2
import grpc

class GreeterStub:
    """The greeting service definition."""
    def __init__(self, channel: grpc.Channel) -> None: ...
    SayHello: grpc.UnaryUnaryMultiCallable[
        greeter_pb2.HelloRequest,
        greeter_pb2.HelloReply]
    """Sends a greeting"""


class GreeterServicer(metaclass=abc.ABCMeta):
    """The greeting service definition."""
    @abc.abstractmethod
    def SayHello(self,
        request: greeter_pb2.HelloRequest,
        context: grpc.ServicerContext,
    ) -> greeter_pb2.HelloReply:
        """Sends a greeting"""
        pass


def add_GreeterServicer_to_server(servicer: GreeterServicer, server: grpc.Server) -> None: ...

运行mypy执行类型检查时,greeter_pb2_grpc.pyi文件抛出如下错误信息:

"UnaryUnaryMultiCallable" expects no type arguments, but 2 given

grpc官方库中UnaryUnaryMultiCallable类的实际定义为:

class UnaryUnaryMultiCallable(six.with_metaclass(abc.ABCMeta)): ...

stubgen工具默认生成的对应类型存根为:

class UnaryUnaryMultiCallable(metaclass=abc.ABCMeta):

需求为不修改mypy-protobuf自动生成的文件,仅调整stubgen生成的存根文件,通过编辑stubgen生成的grpc/__init__.pyi文件消除该mypy类型检查报错。

解决方案

在grpc/__init__.pyi文件中导入typing模块的泛型基类,将所有gRPC调用相关的MultiCallable类声明为接收两个类型参数的泛型类即可,具体修改如下:

  • 在文件顶部添加导入与类型变量声明:
    from typing import TypeVar, Generic
    _RequestType = TypeVar("_RequestType")
    _ResponseType = TypeVar("_ResponseType")
    
  • 找到stubgen原先生成的UnaryUnaryMultiCallable定义,修改为继承Generic[_RequestType, _ResponseType]的泛型类,类下原有方法定义全部保留:
    class UnaryUnaryMultiCallable(Generic[_RequestType, _ResponseType], metaclass=abc.ABCMeta): ...
    
  • (可选,避免后续其他调用模式报同类错误) 对剩下三种MultiCallable类型做同样的泛型声明:
    class UnaryStreamMultiCallable(Generic[_RequestType, _ResponseType], metaclass=abc.ABCMeta): ...
    class StreamUnaryMultiCallable(Generic[_RequestType, _ResponseType], metaclass=abc.ABCMeta): ...
    class StreamStreamMultiCallable(Generic[_RequestType, _ResponseType], metaclass=abc.ABCMeta): ...
    
  • (可选,避免服务端实现报类型匹配错误) 给ServicerContext也补上对应泛型参数声明,类下原有方法全部保留:
    class ServicerContext(Generic[_RequestType, _ResponseType]): ...
    

修改完成后重新运行mypy,UnaryUnaryMultiCallable泛型参数数量不匹配的报错就会消除。

内容的提问来源于stack exchange,提问作者Drarig29

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 20:12:20