Skip to content

ImportError: Cannot Import Name 'soft_unicode' from 'markupsafe'

问题概述

当使用 Docker 容器运行 Apache Airflow 或其他 Python 应用时,可能会遇到以下错误:

python
ImportError: cannot import name 'soft_unicode' from 'markupsafe'

这个错误通常发生在 markupsafe 库升级到 2.1.0+ 版本后,因为这些版本移除了 soft_unicode 函数,而一些依赖库(如旧版 Jinja2)仍然需要这个函数。

根本原因

markupsafe 库在 2.1.0 版本中进行了重大变更,移除了 soft_unicode 函数,转而使用 soft_str 作为替代。这导致了与依赖旧版本接口的库(特别是 Jinja2 2.x)不兼容。

通过 pipdeptree 可以查看依赖关系:

bash
pip install pipdeptree
pipdeptree -r -p markupsafe

会显示:

MarkupSafe==2.1.1
  - Jinja2==2.11.3 [requires: MarkupSafe>=0.23]  # 不兼容

MarkupSafe==2.1.1
  - Jinja2==3.1.2 [requires: MarkupSafe>=2.0]  # 兼容

解决方案

方案一:降级 markupsafe(快速修复)

最直接的解决方法是降级 markupsafe 到 2.0.1 版本:

bash
pip install markupsafe==2.0.1

注意

在某些情况下,可能需要先卸载现有版本:

bash
pip uninstall markupsafe
pip install markupsafe==2.0.1

对于 Docker 环境,在 docker-compose.yml 中添加:

yaml
webserver:
  build:
    args:
      PYTHON_DEPS: MarkupSafe==2.0.1

方案二:升级依赖库(推荐长期方案)

更好的长期解决方案是升级依赖 markupsafe 的库,特别是 Jinja2:

bash
pip install --upgrade Jinja2

这会将 Jinja2 升级到 3.1.2+ 版本,这些版本已经兼容 markupsafe 2.1.0+。

方案三:清理和重新安装

如果上述方法无效,尝试彻底清理并重新安装:

bash
# 删除现有 markupsafe
pip uninstall markupsafe

# 清理残留文件(位置可能因系统而异)
rm -rf /usr/local/lib/python*/site-packages/markupsafe
rm -rf /usr/local/lib/python*/site-packages/MarkupSafe-*.dist-info

# 重新安装兼容版本
pip install markupsafe==2.0.1

方案四:更新整个环境

对于 Anaconda 用户,可以更新整个环境:

bash
conda update anaconda-navigator
conda install conda=23.10.0
conda update anaconda
conda update python
conda install markupsafe

预防措施

  1. 固定关键依赖版本:在 requirements.txt 中固定关键库的版本
  2. 定期更新依赖:定期检查并更新过时的依赖库
  3. 使用虚拟环境:为每个项目创建独立的虚拟环境

最佳实践

建议优先选择升级依赖库(方案二)而不是降级 markupsafe,因为:

  • 保持库的最新版本可获得安全更新和性能改进
  • 避免未来再次遇到类似兼容性问题
  • 符合长期维护的最佳实践

总结

ImportError: cannot import name 'soft_unicode' from 'markupsafe' 错误是由于库版本不兼容导致的。通过降级 markupsafe 或升级依赖库(如 Jinja2)可以解决这个问题。推荐优先考虑升级依赖库的方案,以获得更好的长期兼容性和安全性。