文章目录
Sphinx画流程图和时序图
最近在使用sphinx的时候遇到了一点问题,首先是不支持中文检索,为此进行了一些配置,参考链接
首先安装jieba库,python3的安装命令是:pip install jieba3k
,然后把sphinx项目的conf.py
文件中的language
键值改为 zh_CN
,再进行编译应该就可以了。
配置完之后发现很多目录的内容依旧没有检索到,于是决定稍微深挖一下sphinx在编译的过程中是怎么寻找内容并构建索引的(结论在此)。
首先定位到sphinx的安装目录,并进入这个目录:
import sphinx
print(sphinx.__file__)
跟搜索相关的文件在search/
目录下
sphinx-autobuild
命令是按字典序升序,深度优先搜索每个目录下的每一个rst文件,依次进行构建;检索到的文件会在编译过程中用绿色字体标示出来。当然,如果我们没有手动对sphinx的代码进行修改,添加一些print
语句,编译过程基本都是在同一行内显示,每个文件就闪一下就过去了,基本是看不到的。
接下来一段提及的内容都属于search/__init__.py
文件中的代码:
visitor.found_title_words
返回每个文档的标题文字,标题包括每个文档的开头标题和每一个用=====
,-----
,+++++
等修饰的文字。
IndexBuilder
在初始化后,它的lang
成员根据sphinx项目目录下conf.py
的language
键值的不同,可能是SearchEnglish
类也可能是SearchChinese
类。对IndexBuilder
的调用是在builders/html/__init__.py
里头;
self.indexer = IndexBuilder(self.env, lang,
self.config.html_search_options,
self.config.html_search_scorer)
self.load_indexer(docnames)
第一行的参数没有什么特别,第二个是语言,后两个是空的;docnames
是所有的rst文件的路径,load_indexer()
函数依次给出每个文件的指针,并调用IndexBuilder
的load()
方法令其按sphinx.search._JavaScriptIndex
的方式读取文件,得到的变量frozen
有很多个键值,这里只挑对我们有用的键值出来讲:
docnames: 一个list,包含rst文件在sphinx文档树中的路径(又名索引index),如best_practices/git
filenames: 一个list,包含rst文件的实际相对路径,如best_practices\git.rst
titles: 一个list,包含所有rst文件的大标题(每个文件只有一个大标题)
docnames,filenames和titles三者是一一对应的,顺序也是相同的
objtypes: 一个dict,看起来像是固定的,内容为{'0': 'py:attribute', '1': 'py:class', '2': 'py:method'}
objnames: 一个dict,与objtypes相对应,内容为{'0': ['py', 'attribute', 'Python 属性'], '1': ['py', 'class', 'Python 类'], '2': ['py', 'method', 'Python 方法']}
titleterms: 一个{str: int/list}的dict,保存的是由标题分词得到的索引词与titles所指页面的对应关系,例如{"位置": [4, 27, 32]}
表示位置这个词出现在了titles[4], titles[27], titles[32]所对应的三个页面中,也即三个检索结果。需要注意的是,虽然titles只包含了大标题,但titleterms里头是有包含小标题的分词结果的,也即小标题可以正常搜索,正常对应到某个页面
terms: 与titleterms相似,唯一的不同是它保存了由正文分词得到的索引词与titles所指页面的对应关系
objects: 一个{name: list[list]}的dict,保存被autoclass
和automodule
等引用的模块和类,形如{'mixedai.sys_layer.log': [[26, 0, 1, '', 'logger']], ...}
,key是模块名,相当于from xxx import yyy
里面的xxx
,value是嵌套list,每个list是一条引用,26表示title[26]对应的页面,‘logger’是yyy
;第二项的0与前面objtypes内容相对应,0是属性,1是类,2是方法。第三项和第四项的1和’'没有看出啥名堂来,每一条这两项都是一样的。
回到load()
方法,self._filenames
跟self._titles
分别保存了索引(这里的索引是指形如best_practices/git
的字符串)与文件名、标题名称的对应关系,self._mapping
跟self._title_mapping
分别保存了正文分词、标题行分词与索引index的对应关系,到这里就准备好检索所需的材料了。
stem()
函数在分词之后执行,对分词结果做预处理,如统一变为小写等,这样可以将同类项合并到一个索引中,提高搜索效率和准确度。
接下来一段提及的内容都属于search/zh.py
文件中的代码:
search/zh.py
是针对中文检索的文件,支持jieba库;self.latin_terms
在每次分词的时候都会收录分出来的英文单词,在stem
环节用来判断需不需要做stem
。由于我没有看到过这个条件生效的情况,should_not_be_stemmed
一直都是False,所以这点暂时不管。
结论:要想支持中文检索,安装jieba3k
库就万事大吉了。之所以看起来搜到的结果不够完整, 是因为要保持搜索结果有条理,所以同一个html页面如果出现多次搜索词,只会显示为一条结果,但在点进该页面时会高亮显示每个匹配的词。
如果检索失败,查看编译结果目录下的searchindex.js文件,有\uxxxx
字样就是有中文检索材料,应该是可以检索出来的,没有的话要再回去看看中间过程。
需要借助sphinxcontrib-plantuml
插件:pip install sphinxcontrib-plantuml
,同时在conf.py
中做一些配置:
extensions = [
'sphinxcontrib.plantuml',
]
plantuml = 'java -jar plantuml.1.2021.12.jar'
plantuml的jar文件下载地址在这
另外需要安装jdk,我们需要在Docker中安装jdk,这里使用Docker构建jdk1.8镜像,参考链接。然后还要安装graphviz,不然只能画时序图跟活动图。
Linux版jdk点此下载,提取码是idyn
,资源来自此链接中的评论。
切换主题
这里有很多内置主题,在写普通uml语句的时候通过!theme bluegray
导入主题,现在是在sphinx的一个插件里头使用,它只支持!include
命令,因此只能手动把.puml
文件拉到本地,使用!include
命令导入主题文件。这里提供了内置主题的快速预览。
plantuml官方教程,图文并茂
plantuml刚装好的时候找不到中文,中文会显示成方块,需要安装一下,参考链接
以上n多步最终的Dockerfile如下,ADD涉及的文件都需要手动下载,下载链接在参考链接中或上文中:
FROM xxxx
RUN mkdir /usr/local/jdk && mkdir /usr/local/packages && mkdir -p /usr/share/fonts/simsun && pip install sphinxcontrib-plantuml && apt-get install -y graphviz fontconfig xfonts-utils
ADD jdk-8u281-linux-x64.tar.gz /usr/local/jdk
ADD plantuml.1.2021.12.jar /usr/local/packages
ADD plantuml_official_themes/ /usr/local/packages/plantuml_official_themes/
ADD plantuml-style-c4/ /usr/local/packages/plantuml-style-c4/
ADD simsun.ttc /usr/share/fonts/simsun
RUN mkfontscale && mkfontdir && fc-cache -fv && /bin/bash -c "source /etc/profile"
ENV JAVA_HOME /usr/local/jdk/jdk1.8.0_281
ENV JRE_HOME /usr/local/jdk/jdk1.8.0_281/jre
ENV PATH $JAVA_HOME/bin:$PATH
第一行代码的开头不可以是中文,否则中文会全部变方块,不在第一行就没事,很神奇(后面重新做了一个容器又没有这个问题了,不知道是怎么一回事)
plantuml样式表,所有能改的参数都在这里了
在容器中使用sphinx-autobuild
时报错:OSError: [Errno 28] inotify watch limit reached,这个是宿主机的配置的问题,在宿主机上进行如下配置即可(参考链接1,参考链接2):
# 查看当前的配置,默认值是8192
cat /proc/sys/fs/inotify/max_user_watches
# 临时更改,重启后会失效
sudo sysctl fs.inotify.max_user_watches=1048576
# 永久更改,在文件后面添加一句 fs.inotify.max_user_watches=1048576
sudo vim /etc/sysctl.conf
一些让人摸不着头脑的警告:
def func1(self, p1, p2, p3, p4):
""" balabala.
Args:
p1: xxx
p2: xxx
p3: xxx
"""
注释换行的时候,要跟"""对齐,而不是跟第一个单词对齐,因此要把第三行的e.g跟Args对齐,就不会报warning了。
再来看第二个例子:
def func2(self, p1, p2, p3, p4, p5):
"""balabala
This method will create the following files:
1. p1p1
2. p2p2
Args:
name: xxx
Returns:
str: xxx
"""
也是类似的原因,把1.与2.跟This对齐就不报warning了。