[protocolbuffers/protobuf]默认为 python 实现不一致,使用 cpp 时出现错误

2024-05-11 647 views
3

您使用什么版本的 protobuf 以及什么语言? 版本:3.17.33.18.03.18.13.19.0

语言:Python(版本3.7.23.8.63.9.03.10.0

什么操作系统(Linux、Windows...)和版本? gLinux

您使用什么运行时/编译器(例如,python 版本或 gcc 版本) python 和/或 cpp

你做了什么? 重现该行为的步骤:

运行这个 bash 脚本。请注意,它需要pyenv与 Python 版本一起安装3.7.2

#!/bin/bash

export PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION=cpp
pyenv global 3.7.2
python -mvenv /tmp/venv
. /tmp/venv/bin/activate
python -m pip install protobuf==3.19.0
python -c "from google.protobuf import descriptor_pb2"

你期望看到什么

我希望这个脚本运行时不会出现错误。

你看到了什么?

Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "/tmp/venv/lib/python3.7/site-packages/google/protobuf/descriptor_pb2.py", line 5, in <module>
    from google.protobuf import descriptor as _descriptor
  File "/tmp/venv/lib/python3.7/site-packages/google/protobuf/descriptor.py", line 47, in <module>
    from google.protobuf.pyext import _message
ImportError: cannot import name '_message' from 'google.protobuf.pyext' (/tmp/venv/lib/python3.7/site-packages/google/protobuf/pyext/__init__.py)

确保您包含可以帮助我们调试的信息(完整的错误消息、异常列表、堆栈跟踪、日志)。

这首先被检测为性能问题,因为我们的基准测试开始显示由于库在不知不觉中运行实现而导致的大幅回归python。有关历史的更多背景信息,请参阅此问题

关于您的项目/环境我们还应该了解的其他信息

许多 Python 版本和protobuf库版本的组合都存在问题。以下是我在运行上述复制脚本时发现存在问题的组合:

Python版本 协议缓冲区版本 环境变量状态 结果
3.7.2 3.19.0 未设置 默认python执行不正确
3.7.2 3.19.0 cpp 结果出现上述错误
3.7.2 3.18.1 未设置 默认python执行不正确
3.10.0 3.18.1 未设置 默认python执行不正确
3.7.2 3.18.1 cpp 结果出现上述错误
3.10.0 3.18.1 cpp 结果出现上述错误
3.7.2 3.18.0 未设置 默认python执行不正确
3.10.0 3.18.0 未设置 默认python执行不正确
3.7.2 3.18.0 cpp 结果出现上述错误
3.10.0 3.18.0 cpp 结果出现上述错误
3.10.0 3.17.3 未设置 默认python执行不正确
3.10.0 3.17.3 cpp 结果出现上述错误

回答

9

我最近遇到了此错误的变体,并通过将标志添加--install-option="--cpp_implementation"pip install.我对 Python 不是很了解,也不知道这是否是一个好的解决方案,但也许这个解决方法会有所帮助。

0

(已更新;请参阅评论末尾)

我刚刚开始遇到可能是相关的问题。就我而言,我在 Apple-Silicon Mac(本机;不是 Rosetta)上运行自制安装的 python 3.9.7。如果我执行以下操作:

python3 -m pip install protobuf google-cloud-datastore
...
Successfully installed google-cloud-datastore-2.3.0 protobuf-3.19.1

python3 -c 'from google.cloud import datastore'

我得到:

Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "/opt/homebrew/lib/python3.9/site-packages/google/cloud/datastore/__init__.py", line 59, in <module>
    from google.cloud.datastore.batch import Batch
  File "/opt/homebrew/lib/python3.9/site-packages/google/cloud/datastore/batch.py", line 24, in <module>
    from google.cloud.datastore import helpers
  File "/opt/homebrew/lib/python3.9/site-packages/google/cloud/datastore/helpers.py", line 23, in <module>
    from google.protobuf import struct_pb2
  File "/opt/homebrew/lib/python3.9/site-packages/google/protobuf/struct_pb2.py", line 6, in <module>
    from google.protobuf import descriptor as _descriptor
  File "/opt/homebrew/lib/python3.9/site-packages/google/protobuf/descriptor.py", line 47, in <module>
    from google.protobuf.pyext import _message
AttributeError: module 'google.protobuf.internal.containers' has no attribute 'MutableMapping'

奇怪的是:我有第二台 Mac,其设置非常相同(所有内容都完全相同的 python/pip 版本)并且它可以在那里工作。经过一番挖掘,这似乎是由于第二台 Mac 默认使用 protobuf 中的“python”api_implementation,而第一个 Mac 则获取“cpp”。经过进一步挖掘,我发现这是由于 protobuf 包在第一种情况下安装了 .so 文件,而不是第二种情况。如果我在两台机器上通过相同的方式干净地重新安装 protobuf python3 -m pip install protobuf,我会在 Mac 1 上看到以下结果:

% find /opt/homebrew/lib/python3.9/site-packages/google/protobuf | grep -i \\.so
/opt/homebrew/lib/python3.9/site-packages/google/protobuf/internal/_api_implementation.cpython-39-darwin.so
/opt/homebrew/lib/python3.9/site-packages/google/protobuf/pyext/_message.cpython-39-darwin.so

在 Mac 2 上,它是空的(尽管包的其余部分都在那里)。所以这看起来可能是两个不同的问题:

  • Mac 2 未安装 .so 文件,而 Mac 1 则安装
  • 当 .so 文件存在时,事情就会被破坏

正如我所提到的,两者的软件环境非常相同。 Mac 2 是新的 M1 Max MBP 之一,没有安装 Rosetta,而第一台是安装了 Rosetta 的普通 M1。这些事情中的任何一个都可能成为一个因素吗? (架构是相同的,这都是本机代码,所以我不这么认为,但也许是某种原因?..)

更新:经过更彻底的清理/重新安装后,我在 Mac1 上不再看到 .so 文件。看起来这些是作为依赖项安装的冲突自制 protobuf 包留下的陈旧文件,尽管通过 pip 卸载/重新安装,但它们仍然存在。所以现在我在任何地方都看不到 .so 文件,并且所有内容都通过“python”实现进行工作。所以我猜这就是世界的预期状态,一切都很好。不过,如果我的小发现之旅对任何人都有用,我会保留此评论。

1

@efroemling 我假设你打算使用该python实现,对吗?我相信,缺少.so文件将导致无法使用该实现。cpp

9

我能够重现这个,谢谢。

我认为根本原因是 3.18.0 将我们的平台标签从“manylinux1”移至“manylinux2014”。早期版本的 Python 似乎仍然需要较旧的平台标签,例如 Manylinux1。

此更改是由https://github.com/protocolbuffers/protobuf/pull/8280引起的(cc @jtattermusch)

我认为这里的解决方案可能是针对 x86-64 恢复为 Manylinux1,而针对 aarch64 仅使用 Manylinux2014。

更多详细信息如下:


对于带有 Protobuf 3.17.1 的 Python 3.7.2,它正在安装wheel protobuf-3.17.3-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl

$ python -m pip install protobuf==3.17.3
Collecting protobuf==3.17.3
  Downloading https://files.pythonhosted.org/packages/4c/53/ddcef00219f2a3c863b24288e24a20c3070bd086a1e77706f22994a7f6db/protobuf-3.17.3-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl (1.0MB)
    100% |████████████████████████████████| 1.0MB 25.4MB/s 
Collecting six>=1.9 (from protobuf==3.17.3)
  Downloading https://files.pythonhosted.org/packages/d9/5a/e7c31adbe875f2abbb91bd84cf2dc52d792b5a01506781dbcf25c91daf11/six-1.16.0-py2.py3-none-any.whl
Installing collected packages: six, protobuf
  Found existing installation: protobuf 3.19.1
    Uninstalling protobuf-3.19.1:
      Successfully uninstalled protobuf-3.19.1
Successfully installed protobuf-3.17.3 six-1.16.0

对于 Protobuf 3.19.1,我们似乎没有构建cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64包。以下是为 3.19.1 构建的软件包列表:

protobuf-3.19.1-cp310-cp310-macosx_10_9_universal2.whl 
protobuf-3.19.1-cp310-cp310-manylinux2014_aarch64.whl 
protobuf-3.19.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl 
protobuf-3.19.1-cp36-cp36m-macosx_10_9_x86_64.whl 
protobuf-3.19.1-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl 
protobuf-3.19.1-cp36-cp36m-win32.whl 
protobuf-3.19.1-cp36-cp36m-win_amd64.whl 
protobuf-3.19.1-cp37-cp37m-macosx_10_9_x86_64.whl 
protobuf-3.19.1-cp37-cp37m-manylinux2014_aarch64.whl 
protobuf-3.19.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl 
protobuf-3.19.1-cp37-cp37m-win32.whl 
protobuf-3.19.1-cp37-cp37m-win_amd64.whl 
protobuf-3.19.1-cp38-cp38-macosx_10_9_x86_64.whl 
protobuf-3.19.1-cp38-cp38-manylinux2014_aarch64.whl 
protobuf-3.19.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl 
protobuf-3.19.1-cp38-cp38-win32.whl 
protobuf-3.19.1-cp38-cp38-win_amd64.whl 
protobuf-3.19.1-cp39-cp39-macosx_10_9_x86_64.whl 
protobuf-3.19.1-cp39-cp39-manylinux2014_aarch64.whl 
protobuf-3.19.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl 
protobuf-3.19.1-cp39-cp39-win32.whl 
protobuf-3.19.1-cp39-cp39-win_amd64.whl 
protobuf-3.19.1-py2.py3-none-any.whl 
protobuf-3.19.1.tar.gz

而对于 3.17.3,我们发布了:

protobuf-3.17.3-cp27-cp27m-macosx_10_9_x86_64.whl
protobuf-3.17.3-cp27-cp27mu-manylinux_2_5_x86_64.manylinux1_x86_64.whl
protobuf-3.17.3-cp35-cp35m-macosx_10_9_intel.whl
protobuf-3.17.3-cp35-cp35m-manylinux_2_5_x86_64.manylinux1_x86_64.whl
protobuf-3.17.3-cp35-cp35m-win32.whl
protobuf-3.17.3-cp35-cp35m-win_amd64.whl
protobuf-3.17.3-cp36-cp36m-macosx_10_9_x86_64.whl
protobuf-3.17.3-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl
protobuf-3.17.3-cp36-cp36m-win32.whl
protobuf-3.17.3-cp36-cp36m-win_amd64.whl
protobuf-3.17.3-cp37-cp37m-macosx_10_9_x86_64.whl
protobuf-3.17.3-cp37-cp37m-manylinux2014_aarch64.whl
protobuf-3.17.3-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl
protobuf-3.17.3-cp37-cp37m-win32.whl
protobuf-3.17.3-cp37-cp37m-win_amd64.whl
protobuf-3.17.3-cp38-cp38-macosx_10_9_x86_64.whl
protobuf-3.17.3-cp38-cp38-manylinux2014_aarch64.whl
protobuf-3.17.3-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl
protobuf-3.17.3-cp38-cp38-win32.whl
protobuf-3.17.3-cp38-cp38-win_amd64.whl
protobuf-3.17.3-cp39-cp39-macosx_10_9_x86_64.whl
protobuf-3.17.3-cp39-cp39-manylinux2014_aarch64.whl
protobuf-3.17.3-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.whl
protobuf-3.17.3-cp39-cp39-win32.whl
protobuf-3.17.3-cp39-cp39-win_amd64.whl
protobuf-3.17.3-py2.py3-none-any.whl
protobuf-3.17.3.tar.gz

比较这两个列表我们得到:

-cp27-cp27m-macosx_10_9_x86_64.whl
-cp27-cp27mu-manylinux_2_5_x86_64.manylinux1_x86_64.whl
-cp35-cp35m-macosx_10_9_intel.whl
-cp35-cp35m-manylinux_2_5_x86_64.manylinux1_x86_64.whl
-cp35-cp35m-win32.whl
-cp35-cp35m-win_amd64.whl
+cp310-cp310-macosx_10_9_universal2.whl
+cp310-cp310-manylinux2014_aarch64.whl
+cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
 cp36-cp36m-macosx_10_9_x86_64.whl
-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl
+cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
 cp36-cp36m-win32.whl
 cp36-cp36m-win_amd64.whl
 cp37-cp37m-macosx_10_9_x86_64.whl
 cp37-cp37m-manylinux2014_aarch64.whl
-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl
+cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
 cp37-cp37m-win32.whl
 cp37-cp37m-win_amd64.whl
 cp38-cp38-macosx_10_9_x86_64.whl
 cp38-cp38-manylinux2014_aarch64.whl
-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl
+cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
 cp38-cp38-win32.whl
 cp38-cp38-win_amd64.whl
 cp39-cp39-macosx_10_9_x86_64.whl
 cp39-cp39-manylinux2014_aarch64.whl
-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.whl
+cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
 cp39-cp39-win32.whl
 cp39-cp39-win_amd64.whl
 py2.py3-none-any.whl

我在这里观察到的两个主要变化是:

  1. 我们放弃了 Python 2.7 和 3.5,并添加了 Python 3.10。
  2. 我们已将ABI 目标从manylinux1改为。manylinux2014
8

抄送@jtattermusch

知道如何将 Linux 的 Manylinux2014 恢复为 Manylinux1 吗?

3

我对此进行了调查,发现该问题很可能与我的 PR https://github.com/protocolbuffers/protobuf/pull/8280无关(这只影响构建或 aarch64 轮子,并且不会改变任何内容) x86_64 轮子)。

manylinux1@haberman 是正确的,x86_64 突然从到切换manylinux2014(因此,对于早于 Manylinux2014 支持的系统,只有 protobuf python 的纯 python 版本可用 - 因此没有 cpp 支持,这解释了本期报告的行为) 。

看来从 Manylinux1 到 Manylinux2014 的意外切换实际上并不是由此存储库中的更改引起的,而是由https://github.com/matthew-brett/multibuild中的更改引起的。为了构建 python 轮子,我们使用多重构建脚本,并且总是克隆该存储库的 HEAD,以便该存储库中的任何更改都将在 protobuf 轮子构建中自动获取。 https://github.com/protocolbuffers/protobuf/blob/47e05427e3341c9b18fff047e7d9f79af0dafe9b/kokoro/release/python/linux/build_artifacts.sh#L28

8 月 21 日,matthew-brett/multibuild 已将默认的 Manylinux 映像从 切换12014(请参阅 PR https://github.com/multi-build/multibuild/pull/423/files)。

一些额外的证据:

解决方案比较简单:

  • 确保我们明确设置MB_ML_VER=1x86_64 轮子
  • 将 matthew-brett/multibuild 的克隆固定到特定版本,以避免将来出现此类意外更改。
  • 如果需要的话,还应该可以为旧版本追溯生成缺失的 Manylinux1 轮子。
0

谢谢@jtattermusch - 您是否大致了解此修复程序何时会发布?

4

谢谢@jtattermusch - 您是否大致了解此修复程序何时会发布?

这由 protobuf 团队决定。此外,他们还需要决定是否可能向后移植到现有版本中。

0

非常感谢@jtattermusch。好像 PR 的更新已经停止了,我们可以做些什么来恢复该线程吗?

2

这里同样的问题。修复版本有任何时间表更新吗?

9

我能够AttributeError: module 'google.protobuf.internal.containers' has no attribute 'MutableMapping'通过降级到 protobuf==3.17.3 来摆脱这个问题,如上面的评论之一所示:

$ pip uninstall protobuf
$ pip install protobuf==3.17.3
7

您好,我很想知道 3.20.x 版本是否有时间表?或者是否已在某处宣布/跟踪?

0

包含修复程序的 3.20.0 已经预发布。 Office版本将在这两周内发布

1

@anandolee 感谢您的提醒。您知道此修复是否会重新移植到已经发布的版本吗?如果不是,我们需要排除版本>= 3.18.0, < 3.20.0

2

我们没有向后移植的计划

2

嘿嘿,我们也被这个问题困扰了。此修复程序是在 发布的3.20.0

5

@taliastocks 如果有帮助的话,我们目前正在使用,3.20.0没有问题。我们排除 3.18。和 3.19。, 看这里