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 获取包本身中的所有顶级包名称,并将隐式相对导入替换为绝对导入。
我有一个看起来像这样的包裹:
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 获取包本身中的所有顶级包名称,并将隐式相对导入替换为绝对导入。