Skip to content

解决 TypeError: Descriptors cannot not be created directly 错误

问题描述

当尝试安装或使用 Ray、TensorFlow、Keras 等库时,可能会遇到如下错误:

TypeError: Descriptors cannot not be created directly.
If this call came from a _pb2.py file, your generated code is out of date and must be regenerated with protoc >= 3.19.0.
If you cannot immediately regenerate your protos, some other possible workarounds are:
 1. Downgrade the protobuf package to 3.20.x or lower.
 2. Set PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION=python (but this will use pure-Python parsing and will be much slower).

这个错误通常是由于 Protocol Buffers (protobuf) 包版本不兼容导致的。protobuf 是 Google 开发的用于结构化数据序列化的库,许多机器学习框架和工具都依赖它。

错误原因

错误信息明确指出:当 protobuf 版本过高(特别是从 4.21.0 开始),会导致与之前生成的 Python 协议缓冲区代码不兼容。protobuf 4.x 版本引入了一些重大变更,导致旧代码无法正常工作。

解决方案

解决方案 1:降级 protobuf 版本(推荐)

最常见的解决方案是将 protobuf 降级到兼容版本:

bash
pip install "protobuf<=3.20.1"

或者强制重新安装特定版本:

bash
pip install 'protobuf<=3.20.1' --force-reinstall

也可以使用更宽松的版本约束:

bash
pip install 'protobuf==3.20.*'

TIP

如果项目使用 requirements.txt 文件,添加以下内容到文件末尾以确保覆盖之前的安装:

protobuf==3.20.*

解决方案 2:升级相关依赖

有时,升级依赖库到最新版本可以解决兼容性问题:

bash
# 升级 TensorFlow
pip install tensorflow==2.12.0

# 或者升级其他可能相关的库
pip install wandb --upgrade
pip install streamlit --upgrade

WARNING

请注意,升级主框架(如 TensorFlow)可能会导致其他依赖问题,建议在开发环境中先测试。

解决方案 3:使用环境变量(性能影响)

如果无法立即降级 protobuf,可以使用环境变量作为临时解决方案:

bash
export PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION=python

性能警告

这种方法会强制使用纯 Python 解析器,而不是更快的 C++ 实现,可能会导致性能显著下降。建议仅作为临时解决方案。

解决方案 4:检查间接依赖

有时 protobuf 可能是通过其他依赖安装的,需要检查并调整间接依赖:

bash
# 查看当前安装的 protobuf 版本
pip show protobuf

# 检查哪些包依赖 protobuf
pipdeptree | grep protobuf

如果有冲突的间接依赖(如 googleapis-common-protos),可能需要调整其版本或移除它让其他依赖管理 protobuf 版本。

解决方案 5:使用 Conda 管理依赖

如果使用 Conda 环境,可以尝试用 Conda 安装兼容版本:

bash
pip uninstall protobuf
conda install 'protobuf=3.20.1'

各环境下的具体解决方案

bash
# 对于 TensorFlow 2.9+
pip install tensorflow==2.12.0
pip install "protobuf<=3.20.1"

# 对于 TensorFlow 1.x
pip install protobuf==3.15.0
bash
pip install "protobuf<=3.20.1"
bash
pip install streamlit --upgrade
bash
pip install wandb==0.12.17
bash
pip install google-cloud-audit-log==0.2.4

预防措施

  1. 固定关键依赖版本:在 requirements.txtsetup.py 中明确指定关键依赖的版本范围
  2. 使用虚拟环境:为每个项目创建独立的虚拟环境,避免全局包冲突
  3. 定期更新依赖:定期检查并更新依赖到兼容版本,避免积累过多的版本冲突

总结

TypeError: Descriptors cannot not be created directly 错误通常是由于 protobuf 版本不兼容导致的。最可靠的解决方案是将 protobuf 降级到 3.20.x 或更低版本。如果性能不是主要考虑因素,可以临时设置环境变量作为权宜之计。长期来看,保持依赖库的最新兼容版本是最佳实践。