我有一个 gRPC 服务,python grpc 编译器在
proto
目录中生成了两个文件:
service_pb2.py
service_pb2_grpc.py
在
service_pb2_grpc.py
中有一个导入from proto import service_pb2 as proto_dot__service__pb2
。此导入失败,因为在我的 virtualenv 中,我有另一个名为 proto
的包,它似乎是 google 云日志记录库的依赖项。因此,尝试从站点包导入,而不是从 proto 目录导入。我不想在编译器完成工作后运行一些脚本来重命名这个生成的原型目录。有没有办法告诉 grpc 编译器对包含 proto 的文件夹使用哪个名称?
如果有人在 2024 年处理此问题,“官方解决方法”是将
sys.path
附加到 .proto 文件父目录的路径,从而允许正确处理 service_pb2_grpc.py
中的导入语句。
运行protoc命令,在
__init__.py
文件的父目录下创建.proto
文件
这里是一个脚本,可用于递归处理指定目录下的所有
.proto
文件,生成protobuf文件并创建必要的__init__.py
来解决导入问题。
import os
import subprocess
from client import PROJECT_ROOT
proto_files_dir = os.path.join(PROJECT_ROOT, 'client', 'api')
for dirpath, dirnames, filenames in os.walk(proto_files_dir):
proto_files = [f for f in filenames if f.endswith('.proto')]
if proto_files:
# For each .proto file, run the protoc command to generate the Python files
for proto_file in proto_files:
print(f"Processing .proto file '{proto_file}'...", end=' ')
proto_file_path = os.path.join(dirpath, proto_file)
command = (
f'python3 -m grpc_tools.protoc '
f'--proto_path={dirpath} ' # Use proto_root_dir for --proto_path
f'--python_out={dirpath} '
f'--grpc_python_out={dirpath} '
f'{proto_file_path}'
)
subprocess.run(command, shell=True, check=True)
print("OK!")
# Create __init__.py in the directory of .proto file
init_file_path = os.path.join(dirpath, '__init__.py')
if not os.path.exists(init_file_path):
with open(init_file_path, 'w') as init_file:
init_file.write("import os\nimport sys\n\nsys.path.insert(0, os.path.abspath(os.path.dirname(__file__)))\n")
print(f"Created __init__.py in {dirpath}")
参见问题