在包内导入protobuf生成的模块

10 投票
1 回答
3556 浏览
提问于 2025-04-16 20:09

这是我的目录结构。

.
|-- A
|   |-- B
|   |    `-- b.proto
|   `-- C
|        `-- c.proto
`-- py_gen

我这样编译 test.proto 文件。

protoc --python_out=py_gen/ --proto_path ${ROOT}/A ${ROOT}/A/B/b.proto \
       ${ROOT}/A/C/c.proto

这是我得到的结果。

.
`-- py_gen
          |-- B
          |    `-- b_pb2.py
          `-- C
               `-- c_pb2.py

一切都运行得很好,我可以导入每个模块并使用它们,只要我在我的 PYTHONPATH 中包含 ${ROOT}/A/B/py_gen/B 和 ${ROOT}/A/B/py_gen/C。

问题出现在,比如说,模块 c 导入了 b。这在生成的代码中意味着 c 需要导入

 import B.b_pb2

这是预期的结果,因为“在 Python 中,包通常是通过目录结构来确定的”(来自 protobuf 教程)。但是,我无法导入模块 c,因为它找不到 B.b_pb2.py。目前,为了让它正常工作,我必须在生成的目录 B 和 C 中添加空的 __init__.py 文件。

那么,为什么在生成的目录结构中没有 __init__.py 呢?我是不是忘记了什么?我对 Python 还很陌生,可能在这里忽略了一些明显的东西。不过我读了 Python 的 教程

__init__.py 文件是必需的,以便让 Python 将这些目录视为包含包。

1 个回答

3

简单来说:

import B.b_pb2

这里不需要加 .py 后缀。而且,要让这个工作,B 目录里必须有一个 __init__.py 文件,这个文件可以是空的。这个文件告诉 Python 这是一个 目录。根据我所知道的,protobuf 不会在里面放 __init__.py 文件,但其实也不需要,因为它的目的是只为你生成一个单独的模块。

撰写回答