Protobuf 生成的 Python 包内的隐式相对导入使得无法从外部导入

Implicit relative imports inside of Protobuf-generated Python package make importing from outside impossible

我有一个看起来像这样的包裹:

setup.py
requirements.txt
alphausblue/
    api/
        ripple/
            org_pb2.py
    org/
        v1/
            org_pb2_grpc.py

在 org_pb2_grpc.py 中,我有以下导入行:

from api.ripple import org_pb2 as api_dot_ripple_dot_org__pb2

我遇到的问题是,当我从 alphausblue 目录中导入时,导入工作正常。但是,当我从包中创建一个轮子时,将其上传到 Test PyPI,再次下载并尝试将其导入到这样的测试环境中:

>>> import alphausblue
>>> import alphausblue.org
>>> import alphausblue.org.v1
>>> import alphausblue.org.v1.org_pb2_grpc
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "\anaconda3\envs\test\lib\site-packages\alphausblue\org\v1\org_pb2_grpc.py", line 5, in <module>
    from api.ripple import org_pb2 as api_dot_ripple_dot_org__pb2
ModuleNotFoundError: No module named 'api'

我收到上面的错误。我可以将代码从 alphausblue/ 移动到 /,然后导入工作,但我必须做 org.v1.org_pb2_grpc,这不是我想要的。看来这应该可行,所以我在这里缺少什么?

更新 这似乎是关于 protoc 如何生成 Python 代码的 issue。我将在这里调查可能的解决方案,看看我是否不能自己解决问题。

所以,我尝试了很多方法试图让 Protobuf 做我想做的事,即.. 工作,但无法弄清楚。所以,我修改了构建脚本来做到这一点:

mkdir -p generated/py/alphausblue
python3 -m grpc_tools.protoc -I . --python_out=./generated/py/alphausblue --grpc_python_out=./generated/py/alphausblue \
        ./org/v1/*.proto \
        ./kvstore/v1/*.proto \
        ./iam/v1/*.proto \
        ./admin/v1/*.proto \
        ./cost/v1/*.proto \
        ./billing/v1/*.proto \
        ./operations/v1/*.proto \
        ./preferences/v1/*.proto

python3 -m grpc_tools.protoc -I . --python_out=./generated/py/alphausblue \
        $(for v in $(find ./api -type d); do echo -n "$v/*.proto "; done)

for package in $(find generated/py/alphausblue -mindepth 1 -maxdepth 1 -type d -printf "%f "); do
        echo "Found package ${package}. Beginning replacement"
        find generated/py/alphausblue/. -name '*.py' -exec sed -i -e "s/from ${package}/from alphausblue.${package}/g" {} \;
done

此处的前两个命令从 .proto 文件生成 Python 代码。下一个命令使用 find 和 sed 获取包本身中的所有顶级包名称,并将隐式相对导入替换为绝对导入。