Python 始终重新生成包含特定指令的Sphinx文档
Sphinx通常以增量方式构建文档,这意味着只会重新生成已更改的文件。我想知道是否有办法告诉Sphinx总是重新生成某些文件,这些文件可能没有直接更改,但会受到其他文件更改的影响。更具体地说:有没有办法告诉Sphinx始终重新生成包含特定指令的文件?我正在使用的文档依赖于在指令的帮助下从其他页面收集和重新格式化信息的可能性。一个干净的(Python 始终重新生成包含特定指令的Sphinx文档,python,python-sphinx,docutils,Python,Python Sphinx,Docutils,Sphinx通常以增量方式构建文档,这意味着只会重新生成已更改的文件。我想知道是否有办法告诉Sphinx总是重新生成某些文件,这些文件可能没有直接更改,但会受到其他文件更改的影响。更具体地说:有没有办法告诉Sphinx始终重新生成包含特定指令的文件?我正在使用的文档依赖于在指令的帮助下从其他页面收集和重新格式化信息的可能性。一个干净的(makeclean&&make[html])和/或完整的(sphinx构建-A)构建比增量构建花费的时间要长得多。此外,手动跟踪包含该指令的文件可能会很复杂。该文
makeclean&&make[html]
)和/或完整的(sphinx构建-A
)构建比增量构建花费的时间要长得多。此外,手动跟踪包含该指令的文件可能会很复杂。该文档由10多名在编写Sphinx文档方面经验有限的作者编写
但即使在不太复杂的情况下,您也可能面临这个“问题”:
例如,包含一个名为todolist
的指令,该指令从整个文档中收集TODO。如果我创建了一个包含文档中所有TODO的文件(基本上是一个只包含todolist
指令的空文档),则列表不会更新,直到我创建了一个干净的构建或修改了该文件
如果您想自己测试它:使用sphinx quickstart
创建一个文档,并坚持默认值,除了
'> todo: write "todo" entries that can be shown or hidden on build (y/n) [n]: y'
在source
中添加一个名为todos.rst
的文件,并从index.rst
中引用此文件
索引.rst的内容
:
Welcome to sphinx-todo's documentation!
=======================================
.. toctree::
:maxdepth: 2
todos
.. todo::
I have to do this
Indices and tables
==================
* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`
.. _`todos`:
List of ToDos
=============
.. todolist::
todos.rst的内容:
Welcome to sphinx-todo's documentation!
=======================================
.. toctree::
:maxdepth: 2
todos
.. todo::
I have to do this
Indices and tables
==================
* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`
.. _`todos`:
List of ToDos
=============
.. todolist::
假设您使用html
输出,您会注意到当您将todo添加到index.html
时,todos.html
不会改变
tl;dr:如果可能的话,我如何在Sphinx的增量构建中包含包含特定指令的文件(例如,
todolist
),而不需要手动跟踪它们 默认情况下,Sphinx将仅更新新文件或更改文件的输出。这是埋在地下的
在sphinx build
的命令选项文档末尾:
您还可以在源目录和生成目录之后的命令行上指定一个或多个文件名。然后Sphinx将尝试只构建这些输出文件(及其依赖项)
您可以直接调用sphinx build,也可以通过makefile调用,具体取决于sphinx版本附带的makefile(您也可以自定义makefile)。仅供记录:我对几个解决方案进行了基准测试 我在我的
conf.py
中创建了一个名为touch_files
的函数。它搜索文件中的字符串,如果找到,则触摸文件以触发重新生成的字符串:
def touch_files(*args):
# recursively search the 'source' directory
for root, dirnames, filenames in os.walk('.'):
# check all rst files
for filename in fnmatch.filter(filenames, '*.rst'):
cur = os.path.join(root, filename)
f = open(cur)
# access content directly from disk
s = mmap.mmap(f.fileno(), 0, access=mmap.ACCESS_READ)
if any(s.find(d) != -1 for d in args):
# if a string pattern has been found alter the edit
# time of the file
os.utime(cur, None)
f.close()
# actually call the function
touch_files('.. todolist::')
touch_files
可以使用可变数量的参数调用,并在找到其中一个参数时编辑文件。我试图用正则表达式优化函数,但效果不太好。使用mmap
直接从磁盘读取文件内容似乎影响不大
这是总共78个文件的结果,其中36个包含两个指令之一
Command Time Comment
time make html 2.3 s No changes
time sh -c 'make clean && make html' 13.3 s
time make htmlfull 9.4 s sphinx-build -a
time make html 8.4 s with 'touch_files'
'touch_files' 0.2 s tested with testit
结果:每个命令只被调用过几次(除了“touch_文件”),因此缺乏统计可靠性。Sphinx大约需要2.3秒来检查文档中的更改,而不做任何操作。一个干净的构建需要13.3秒,这比使用sphinx构建-A
的构建要长得多。如果我们只是重建78个文件中的36个,构建过程会稍微快一点,尽管我怀疑这里是否存在显著差异。“触摸文件”的开销相当低。与编辑时间戳相比,查找字符串非常便宜
结论:正如所指出的,使用
斯芬克斯构建-a
似乎是最合理的方法。至少在我的用例中是这样。如果一个文件不包含有问题的指令会导致长时间的构建touch\u文件
可能会很有用。谢谢您的回答。您的回答支持我目前的印象,即您要么必须构建所有内容,要么直接指定要重建的文件。我希望为指令/文件或一些最佳预处理实践(例如,构建挂钩之前)提供一个整洁的隐藏的“白名单”关键字,但这似乎并不存在。显然,您可以使用BuildEnvironment.note_reread()
在指令中,通过指令的run()
中的self.env
访问构建环境的实例。