Read the Docs build失败: Could not import extension sphinxcontrib.video

最近在引入 Sphinx文档嵌入视频Sphinx文档嵌入YouTube视频 到我的 Sphinx 项目,我在 source 目录下的 requirements.txt 加入了:

requirements.txt 加入模块
sphinx
sphinx_rtd_theme
docutils
sphinxnotes-strike
sphinxcontrib-newsfeed
sphinxcontrib-youtube
sphinxcontrib-video

但是我发现在 Read the Docs 平台,最近的build失败,提示错误如下:

Read the Docs 平台Build失败输出信息
python -m sphinx -T -E -b html -d _build/doctrees -D language=zh_CN . $READTHEDOCS_OUTPUT/html
Running Sphinx v1.8.6
loading translations [zh_CN]... done

Traceback (most recent call last):
  File "/home/docs/checkouts/readthedocs.org/user_builds/cloud-atlas/envs/latest/lib/python3.7/site-packages/sphinx/registry.py", line 472, in load_extension
    mod = __import__(extname, None, None, ['setup'])
  File "/home/docs/checkouts/readthedocs.org/user_builds/cloud-atlas/envs/latest/lib/python3.7/site-packages/sphinxcontrib/video.py", line 12, in <module>
    from sphinx.util.docutils import SphinxDirective, SphinxTranslator
ImportError: cannot import name 'SphinxTranslator' from 'sphinx.util.docutils' (/home/docs/checkouts/readthedocs.org/user_builds/cloud-atlas/envs/latest/lib/python3.7/site-packages/sphinx/util/docutils.py)

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/docs/checkouts/readthedocs.org/user_builds/cloud-atlas/envs/latest/lib/python3.7/site-packages/sphinx/cmd/build.py", line 303, in build_main
    args.tags, args.verbosity, args.jobs, args.keep_going)
  File "/home/docs/checkouts/readthedocs.org/user_builds/cloud-atlas/envs/latest/lib/python3.7/site-packages/sphinx/application.py", line 228, in __init__
    self.setup_extension(extension)
  File "/home/docs/checkouts/readthedocs.org/user_builds/cloud-atlas/envs/latest/lib/python3.7/site-packages/sphinx/application.py", line 449, in setup_extension
    self.registry.load_extension(self, extname)
  File "/home/docs/checkouts/readthedocs.org/user_builds/cloud-atlas/envs/latest/lib/python3.7/site-packages/sphinx/registry.py", line 475, in load_extension
    raise ExtensionError(__('Could not import extension %s') % extname, err)
sphinx.errors.ExtensionError: Could not import extension sphinxcontrib.video (exception: cannot import name 'SphinxTranslator' from 'sphinx.util.docutils' (/home/docs/checkouts/readthedocs.org/user_builds/cloud-atlas/envs/latest/lib/python3.7/site-packages/sphinx/util/docutils.py))

Extension error:
Could not import extension sphinxcontrib.video (exception: cannot import name 'SphinxTranslator' from 'sphinx.util.docutils' (/home/docs/checkouts/readthedocs.org/user_builds/cloud-atlas/envs/latest/lib/python3.7/site-packages/sphinx/util/docutils.py))

这里导入 sphinxcontrib.video 触发了 sphinx.util.docutils 无法导入 SphinxTranslator 模块。

Read the Docs 类似问题在之前遇到过 Sphinx Build Filed: TypeError: ‘generator’… ,主要是 RTD reproducible Builds 需要明确的依赖包版本

需要重新修订配置文件了,之前 Sphinx Build Filed: TypeError: ‘generator’… 修订过配置,随着时间推移又出现新的问题了。需要配置成和当前本地环境一致,这样可以引导 Read the Docs 按照我本地build方式build

.readthedocs.yaml 配置文件

  • 修订项目目录下添加一个配置文件 .readthedocs.yaml ,这次参考 Configuration file v2 修改:

# File: .readthedocs.yaml
# Read the Docs configuration file
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details

# Required
version: 2

# Set the version of Python and other tools you might need
build:
  os: ubuntu-22.04
  tools:
    python: "3.10.6"

# Build documentation in the source/ directory with Sphinx
sphinx:
  configuration: source/conf.py

# If using Sphinx, optionally build your docs in additional formats such as PDF
# formats:
#    - pdf

# Optionally declare the Python requirements required to build your docs
python:
  install:
    - requirements: source/requirements.txt

配置Python依赖的 requirements 文件

之前在 source 目录下 requirements.txt 文件只指定需要哪些模块,但是不指定版本。为了能够更好完成build,改进成指定版本(和本地版本一致)

  • 更新 requirements.txt :

生成 Python virtualenv 所使用Python软件包依赖列表 requirements.txt
pip freeze > source/requirements.txt

现在似乎不再使用 environment.yaml ,我移除了这个配置文件

build的新问题

完成上述配置修订后,推送到Read the docs的build输出果然不同,但是却出现了新的问题(显示安装依赖包出错):

Read the Docs 平台Build失败显示安装包出错
python -m pip install --exists-action=w --no-cache-dir -r source/requirements.txt

Requirement already satisfied: alabaster==0.7.13 in /home/docs/checkouts/readthedocs.org/user_builds/cloud-atlas/envs/latest/lib/python3.7/site-packages (from -r source/requirements.txt (line 1)) (0.7.13)
Requirement already satisfied: Babel==2.12.1 in /home/docs/checkouts/readthedocs.org/user_builds/cloud-atlas/envs/latest/lib/python3.7/site-packages (from -r source/requirements.txt (line 2)) (2.12.1)
Requirement already satisfied: certifi==2022.12.7 in /home/docs/checkouts/readthedocs.org/user_builds/cloud-atlas/envs/latest/lib/python3.7/site-packages (from -r source/requirements.txt (line 3)) (2022.12.7)
Requirement already satisfied: charset-normalizer==3.1.0 in /home/docs/checkouts/readthedocs.org/user_builds/cloud-atlas/envs/latest/lib/python3.7/site-packages (from -r source/requirements.txt (line 4)) (3.1.0)
Collecting docutils==0.18.1
  Downloading docutils-0.18.1-py2.py3-none-any.whl (570 kB)
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 570.0/570.0 kB 104.7 MB/s eta 0:00:00
Requirement already satisfied: idna==3.4 in /home/docs/checkouts/readthedocs.org/user_builds/cloud-atlas/envs/latest/lib/python3.7/site-packages (from -r source/requirements.txt (line 6)) (3.4)
Requirement already satisfied: imagesize==1.4.1 in /home/docs/checkouts/readthedocs.org/user_builds/cloud-atlas/envs/latest/lib/python3.7/site-packages (from -r source/requirements.txt (line 7)) (1.4.1)
Collecting Jinja2==3.1.2
  Downloading Jinja2-3.1.2-py3-none-any.whl (133 kB)
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 133.1/133.1 kB 217.3 MB/s eta 0:00:00
Requirement already satisfied: MarkupSafe==2.1.2 in /home/docs/checkouts/readthedocs.org/user_builds/cloud-atlas/envs/latest/lib/python3.7/site-packages (from -r source/requirements.txt (line 9)) (2.1.2)
Requirement already satisfied: packaging==23.0 in /home/docs/checkouts/readthedocs.org/user_builds/cloud-atlas/envs/latest/lib/python3.7/site-packages (from -r source/requirements.txt (line 10)) (23.0)
Requirement already satisfied: Pygments==2.14.0 in /home/docs/checkouts/readthedocs.org/user_builds/cloud-atlas/envs/latest/lib/python3.7/site-packages (from -r source/requirements.txt (line 11)) (2.14.0)
Requirement already satisfied: requests==2.28.2 in /home/docs/checkouts/readthedocs.org/user_builds/cloud-atlas/envs/latest/lib/python3.7/site-packages (from -r source/requirements.txt (line 12)) (2.28.2)
Requirement already satisfied: snowballstemmer==2.2.0 in /home/docs/checkouts/readthedocs.org/user_builds/cloud-atlas/envs/latest/lib/python3.7/site-packages (from -r source/requirements.txt (line 13)) (2.2.0)
ERROR: Ignored the following versions that require a different python version: 6.0.0 Requires-Python >=3.8; 6.0.0b1 Requires-Python >=3.8; 6.0.0b2 Requires-Python >=3.8; 6.0.1 Requires-Python >=3.8; 6.1.0 Requires-Python >=3.8; 6.1.1 Requires-Python >=3.8; 6.1.2 Requires-Python >=3.8; 6.1.3 Requires-Python >=3.8
ERROR: Could not find a version that satisfies the requirement Sphinx==6.1.3 (from versions: 0.1.61611, 0.1.61798, 0.1.61843, 0.1.61945, 0.1.61950, 0.2, 0.3, 0.4, 0.4.1, 0.4.2, 0.4.3, 0.5, 0.5.1, 0.5.2b1, 0.5.2, 0.6b1, 0.6, 0.6.1, 0.6.2, 0.6.3, 0.6.4, 0.6.5, 0.6.6, 0.6.7, 1.0b1, 1.0b2, 1.0, 1.0.1, 1.0.2, 1.0.3, 1.0.4, 1.0.5, 1.0.6, 1.0.7, 1.0.8, 1.1, 1.1.1, 1.1.2, 1.1.3, 1.2b1, 1.2b2, 1.2b3, 1.2, 1.2.1, 1.2.2, 1.2.3, 1.3b1, 1.3b2, 1.3b3, 1.3, 1.3.1, 1.3.2, 1.3.3, 1.3.4, 1.3.5, 1.3.6, 1.4a1, 1.4b1, 1.4, 1.4.1, 1.4.2, 1.4.3, 1.4.4, 1.4.5, 1.4.6, 1.4.7, 1.4.8, 1.4.9, 1.5a1, 1.5a2, 1.5b1, 1.5, 1.5.1, 1.5.2, 1.5.3, 1.5.4, 1.5.5, 1.5.6, 1.6b1, 1.6b2, 1.6b3, 1.6.1, 1.6.2, 1.6.3, 1.6.4, 1.6.5, 1.6.6, 1.6.7, 1.7.0b1, 1.7.0b2, 1.7.0, 1.7.1, 1.7.2, 1.7.3, 1.7.4, 1.7.5, 1.7.6, 1.7.7, 1.7.8, 1.7.9, 1.8.0b1, 1.8.0, 1.8.1, 1.8.2, 1.8.3, 1.8.4, 1.8.5, 1.8.6, 2.0.0b1, 2.0.0b2, 2.0.0, 2.0.1, 2.1.0, 2.1.1, 2.1.2, 2.2.0, 2.2.1, 2.2.2, 2.3.0, 2.3.1, 2.4.0, 2.4.1, 2.4.2, 2.4.3, 2.4.4, 2.4.5, 3.0.0b1, 3.0.0, 3.0.1, 3.0.2, 3.0.3, 3.0.4, 3.1.0, 3.1.1, 3.1.2, 3.2.0, 3.2.1, 3.3.0, 3.3.1, 3.4.0, 3.4.1, 3.4.2, 3.4.3, 3.5.0, 3.5.1, 3.5.2, 3.5.3, 3.5.4, 4.0.0b1, 4.0.0b2, 4.0.0, 4.0.1, 4.0.2, 4.0.3, 4.1.0, 4.1.1, 4.1.2, 4.2.0, 4.3.0, 4.3.1, 4.3.2, 4.4.0, 4.5.0, 5.0.0b1, 5.0.0, 5.0.1, 5.0.2, 5.1.0, 5.1.1, 5.2.0, 5.2.0.post0, 5.2.1, 5.2.2, 5.2.3, 5.3.0)
ERROR: No matching distribution found for Sphinx==6.1.3

仔细看了日志输出,发现 RTD 使用的 Python 版本低于 3.8 ,导致不满足 Sphinx==6.1.3 的要求

奇怪,我配置了项目目录下 .readthedocs.yaml 指定了 python: "3.10.6" (我根据我本地 Ubuntu Linux 22.04.2 LTS当前发行版Python版本)为何没有生效?

看了Sphinx官方 .readthedocs.yaml 配置 RTD reproducible Builds 采用 python: "3.11" ,但是我依样画葫芦也不行,从build日志来看,RTD依然使用了 Python 3.7:

...
python3.7 -mvirtualenv $READTHEDOCS_VIRTUALENV_PATH
...
../../../_images/marmot.gif

我发现我犯了一个 愚蠢的低级错误 : 现在我为了避免每次 make html 之后不断生成的变化的html被同步到github仓库,我每次只 git add 子目录 source ,根本没有提交上一级项目根目录下的 .readthedocs.yaml ,难怪RTD根本没有按照预想的那样使用高版本Python…

重新推送了 .readthedocs.yaml ,OK

参考