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

使用Bazel构建并运行Python gRPC服务器时遭遇Protobuf版本冲突的问题咨询

Bazel构建并运行Python gRPC服务器时遭遇Protobuf版本冲突的问题咨询

我正在尝试搭建一个更大型的Bazel基础设施,主要想实现两个目标:

  • 用rules_proto_grpc_python从.proto文件生成适配gRPC的.py文件
  • 通过py_binary运行实现了上述接口的服务器代码

但我遇到了下面这个错误:

google.protobuf.runtime_version.VersionError: Detected incompatible Protobuf Gencode/Runtime versions
when loading helloworld/hello.proto: gencode 5.29.1 runtime 5.27.2. Runtime version
cannot be older than the linked gencode version. See Protobuf version
guarantees at https://protobuf.dev/support/cross-version-runtime-guarantee.

这个错误说明rules_proto_grpc_python用来生成.py文件的Protobuf版本,和运行时依赖的Protobuf版本不匹配。我尝试给py_binary指定protobuf>=5.29.1的依赖,但因为项目里其他包的版本冲突,这个方案走不通。在这个最小复现示例里虽然确实能这么做,但会弹出一堆关于冲突符号链接的警告,这看起来也很有隐患。

所以我想请教有没有办法做到以下两点之一:

  • 给rules_proto_grpc_python指定要使用的Protobuf版本
  • 换一种方式从.proto文件生成对应的.py文件?

编辑于2025-02-27

我在大型仓库里反复调整依赖配置后,终于让它正常运行了——只需要指定Protobuf的最低版本就解决了问题。


以下是最小复现示例的相关文件:

顶层MODULE.bazel文件

# MODULE.bazel

bazel_dep(name = "aspect_bazel_lib", version = "2.7.8")
bazel_dep(name = "aspect_rules_py", version = "1.3.2")
bazel_dep(name = "rules_python", version = "1.1.0")
bazel_dep(name = "rules_proto", version = "7.1.0")
bazel_dep(name = "rules_proto_grpc_python", version = "5.0.0")


# deps for python projects.
_PY_MINOR_VER = 10

_PY_VERSION = "3.%s" % _PY_MINOR_VER

_PY_VER_ = "python_3_%s" % _PY_MINOR_VER

python = use_extension("@rules_python//python/extensions:python.bzl", "python")
python.toolchain(
    python_version = _PY_VERSION,
    is_default = True,
)

# You can use this repo mapping to ensure that your BUILD.bazel files don't need
# to be updated when the python version changes to a different `3.12` version.
use_repo(
    python,
    "python_3_%s" % _PY_MINOR_VER,
)

pip = use_extension("@rules_python//python/extensions:pip.bzl", "pip")
pip.parse(
    hub_name = "pypi",
    # We need to use the same version here as in the `python.toolchain` call.
    python_version = _PY_VERSION,
    requirements_lock = "//:requirements_lock.txt",
)
use_repo(pip, "pypi")

/proto_library/proto/hello.proto文件

# proto_library/proto/hello.proto

syntax = "proto3";

package helloworld;

// The greeting service definition.
service Greeter {
  // Sends a greeting
  rpc SayHello (HelloRequest) returns (HelloReply) {}
}

// The request message containing the user's name.
message HelloRequest {
  string name = 1;
}

// The response message containing the greetings
message HelloReply {
  string message = 1;
}

proto文件同目录下的BUILD.bazel文件

# proto_library/proto/BUILD.bazel

load("@rules_proto//proto:defs.bzl", "proto_library")
load("@rules_proto_grpc_python//:defs.bzl", "py_proto_library", "py_grpc_library")


proto_library(
    name = "hello_proto",
    srcs = ["hello.proto"],
    # Add these to control Python package structure
    strip_import_prefix = "/proto_library/proto",
    import_prefix = "helloworld",
    visibility = ["//visibility:public"],
)

py_proto_library(
    name = "hello_py_proto",
    protos = [":hello_proto"],
    visibility = ["//visibility:public"],
)

py_grpc_library(
    name = "hello_py_grpc",
    protos = [":hello_proto"],
    visibility = ["//visibility:public"],
    deps = [":hello_py_proto"],
)

实现服务器逻辑的Python代码

# proto_library/src/hello_server.py

import logging
import sys
from concurrent import futures

import grpc
from helloworld import hello_pb2, hello_pb2_grpc


class Greeter(hello_pb2_grpc.GreeterServicer):
    def SayHello(self, request, context):
        return hello_pb2.HelloReply(message="Hello, %s!" % request.name)


def serve():
    port = "50051"
    server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
    hello_pb2_grpc.add_GreeterServicer_to_server(Greeter(), server)
    server.add_insecure_port("[::]:" + port)
    server.start()
    print("Server started, listening on " + port)
    server.wait_for_termination()


if __name__ == "__main__":
    logging.basicConfig()
    serve()

proto_library目录下的BUILD文件

# proto_library/BUILD.bazel

load("@aspect_rules_py//py:defs.bzl", "py_binary", "py_library")
load("@pypi//:requirements.bzl", "requirement")


py_binary(
    name = "hello_test",
    srcs = ["src/hello_server.py"],
    deps = [
        "//proto_library/proto:hello_py_proto",
        "//proto_library/proto:hello_py_grpc",
        requirement("grpcio"),
        requirement("protobuf"),
    ],
    # Add these to handle Python packaging
    imports = [".."],  # Make parent directories importable
    visibility = ["//visibility:public"],
    package_collisions = "warning",
    # Create proper Python package structure
    main = "hello_server.py",
)

备注:内容来源于stack exchange,提问作者kgully

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.14 11:52:59