Python导入Protoc生成的gRPC pb2文件时遇ModuleNotFoundError
Python导入Protoc生成的gRPC模块遇ModuleNotFoundError问题
项目环境与问题描述
- 项目结构:
test/api/grpc_test_cases/specific_folder目录下包含:proto_files文件夹:存放所有.proto文件(D.proto、A.proto、B.proto、C.proto)test.py:测试文件- 已通过protoc生成的pb2文件(如api_pb2.py)
- 导入报错:执行
from file.innerfile.innermostfile.api.api_pb2 import ServiceRequest时,抛出ModuleNotFoundError: No module named 'api_pb2' - 期望目标:成功导入
ServiceRequest,用于pytest测试并创建请求对象:response = ServiceRequest() response.name = "John" response.id = 123 response.timestamp = "2023-09-18T12:00:00"
已执行的protoc编译命令
- 先编译依赖文件D.proto:
python3 \ -m grpc_tools.protoc \ -I proto_files \ --python_out=. \ --grpclib_python_out=. \ D.proto - 再编译依赖D.proto的其他文件:
python3 \ -m grpc_tools.protoc \ -I proto_files \ --python_out=. \ --grpclib_python_out=. \ proto_files/A.proto \ proto_files/B.proto \ proto_files/C.proto
已尝试的解决方法
- 检查Python路径,确保生成的模块在搜索路径中
- 切换导入语句的相对路径与绝对路径
- 使用单个编译命令生成所有protobuf文件
- 在grpc.py文件中添加
from . import api_pb2
解决方案
1. 修正包结构,确保目录为Python包
在specific_folder目录下创建空的__init__.py文件,让该目录被Python识别为合法包。
2. 调整protoc编译命令,匹配包结构
编译时指定正确的输出目录,确保生成的pb2文件的内部导入语句符合项目层级,避免依赖找不到的情况。统一编译所有proto文件的命令如下:
python3 -m grpc_tools.protoc \ -I ./test/api/grpc_test_cases/specific_folder/proto_files \ --python_out=./test/api/grpc_test_cases/specific_folder \ --grpclib_python_out=./test/api/grpc_test_cases/specific_folder \ ./test/api/grpc_test_cases/specific_folder/proto_files/D.proto \ ./test/api/grpc_test_cases/specific_folder/proto_files/A.proto \ ./test/api/grpc_test_cases/specific_folder/proto_files/B.proto \ ./test/api/grpc_test_cases/specific_folder/proto_files/C.proto
该命令会将生成的pb2文件直接输出到specific_folder目录下,与test.py同层级。
3. 使用正确的导入语句
根据文件层级调整导入路径:
- 如果
test.py在specific_folder下,使用相对导入:from .api_pb2 import ServiceRequest - 或者使用绝对导入(确保项目根目录在Python搜索路径中):
from test.api.grpc_test_cases.specific_folder.api_pb2 import ServiceRequest
4. 确保项目根目录在Python搜索路径中
如果运行pytest时仍有路径问题,可在test.py开头添加以下代码,将项目根目录加入Python路径:
import sys from pathlib import Path # 根据实际项目层级调整parent的数量,确保指向项目根目录 sys.path.append(str(Path(__file__).parent.parent.parent.parent))
内容的提问来源于stack exchange,提问作者ggare
相关产品推荐
相关产品推荐

