使用rst2pdf实现将sphinx生成PDF


Posted in Python onJune 07, 2016

当初项目文档是用sphinx写的,一套rst下来make html得到一整个漂亮的在线文档。现在想要将文档导出为离线的handbook pdf,于是找到了rst2pdf这个项目,作为sphinx的拓展,然后加上少量配置即可输出中文PDF。

rst2pdf

简介

使用rst2pdf实现将sphinx生成PDF

rst2pdf是一个将 reStructuredText 转换为 PDF 的工具,具有下列特性:

  1. 自定义页面布局
  2. 支持层叠样式表
  3. 支持内嵌TTF和Type1字体
  4. 支持几乎所有语言的语法高亮
  5. 使用reStructuredText作为源文件
  6. 支持字间距调整

安装

easy_install rst2pdf

配置rst2pdf

注册到sphinx项目

需要告诉sphinx我们安装了rst2pdf,并且将其作为插件使用。只需在项目根目录下的conf.py中配置:

# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = [
  'sphinx.ext.autodoc',
  'rst2pdf.pdfbuilder'
]

即可。然后,在conf.py中拷入PDF相关的配置:

# -- Options for PDF output --------------------------------------------------
 
# Grouping the document tree into PDF files. List of tuples
# (source start file, target name, title, author, options).
#
# If there is more than one author, separate them with \\.
# For example: r'Guido van Rossum\\Fred L. Drake, Jr., editor'
#
# The options element is a dictionary that lets you override
# this config per-document.
# For example,
# ('index', u'MyProject', u'My Project', u'Author Name',
# dict(pdf_compressed = True))
# would mean that specific document would be compressed
# regardless of the global pdf_compressed setting.
 
pdf_documents = [
  ('index', u'HanLP Handbook', u'HanLP Handbook', u'hankcs'),
]
 
# A comma-separated list of custom stylesheets. Example:
pdf_stylesheets = ['a3','zh_CN']
 
# Create a compressed PDF
# Use True/False or 1/0
# Example: compressed=True
#pdf_compressed = False
 
# A colon-separated list of folders to search for fonts. Example:
pdf_font_path = ['C:\\Windows\\Fonts']
 
# Language to be used for hyphenation support
pdf_language = "zh_CN"
 
# Mode for literal blocks wider than the frame. Can be
# overflow, shrink or truncate
pdf_fit_mode = "shrink"
 
# Section level that forces a break page.
# For example: 1 means top-level sections start in a new page
# 0 means disabled
#pdf_break_level = 0
 
# When a section starts in a new page, force it to be 'even', 'odd',
# or just use 'any'
#pdf_breakside = 'any'
 
# Insert footnotes where they are defined instead of
# at the end.
#pdf_inline_footnotes = True
 
# verbosity level. 0 1 or 2
#pdf_verbosity = 0
 
# If false, no index is generated.
#pdf_use_index = True
 
# If false, no modindex is generated.
#pdf_use_modindex = True
 
# If false, no coverpage is generated.
#pdf_use_coverpage = True
 
# Documents to append as an appendix to all manuals.
#pdf_appendices = []
 
# Enable experimental feature to split table cells. Use it
# if you get "DelayedTable too big" errors
#pdf_splittables = False
 
# Set the default DPI for images
#pdf_default_dpi = 72
 
# Enable rst2pdf extension modules (default is only vectorpdf)
# you need vectorpdf if you want to use sphinx's graphviz support
#pdf_extensions = ['vectorpdf']
 
# Page template name for "regular" pages
#pdf_page_template = 'cutePage'
 
# Show Table Of Contents at the beginning?
# pdf_use_toc = False
 
# How many levels deep should the table of contents be?
pdf_toc_depth = 2
 
# Add section number to section references
pdf_use_numbered_links = False
 
# Background images fitting mode
pdf_fit_background_mode = 'scale'

具体配置项的值请自行调整,不需要严格按照我的来。

样式表

在项目根目录下创建一个zh_CN.json,写入:

{
 "embeddedFonts": [
  "simsun.ttc"
 ],
 "fontsAlias": {
  "stdFont": "simsun",
  "stdBold": "simsun",
  "stdItalic": "simsun",
  "stdBoldItalic": "simsun",
  "stdMono": "simsun",
  "stdMonoBold": "simsun",
  "stdMonoItalic": "simsun",
  "stdMonoBoldItalic": "simsun",
  "stdSans": "simsun",
  "stdSansBold": "simsun",
  "stdSansItalic": "simsun",
  "stdSansBoldItalic": "simsun"
 },
 "styles": [
  [
   "base",
   {
    "wordWrap": "CJK"
   }
  ],
  [
   "literal",
   {
    "wordWrap": "None"
   }
  ]
 ]
}

关于以上样式的说明:

embeddedFonts用于嵌入字体,经试验,必须包含至少四个值才不会报错。不过这四个字体值可以是重复的。

fontsAlias用来指定各类字形用什么字体。如stdFont指正文字体,stdBold指粗体,stdItalic指斜体。其他的还有stdBoldItalic粗斜体,stdMono等宽体,等等。确保所用字体已经安装在你的操作系统上,且字体必须是TTF类型的(Windows环境下限制比较多~)。

wordWrap用于指定换行规则,CJK就是适用于中日韩文字的规则。这是从网上的模板抄来的,但经我的测试发现,如果用CJK规则的话,中英混排的文档里面英文部分就没法正常断行,这真是个遗憾。实际上,fontsAlias的分类很多都只对英文字体有意义,如严格来讲中文是没有所谓斜体的(不过因为Word的普及,经常看到中文被设置为斜体的情形)。如果是纯中文文档,当然随便用哪些中文字体都行,如宋体。现实中,经常会有中英文混排的情形,所以如果全用中文字体的话,英文部分就没法显示斜体等字形了。

关于pdf_stylesheets的说明:这个参数中默认使用的某些样式包含了一些字体,而这些字体并非在所有操作系统上都找得到。'sphinx'和'kerning'都是默认提供的样式,要么不用它们,要么直接修改其包含的字体。'a4'指设置输出的PDF为A4纸大小。默认的样式文件可以在rst2pdf的安装路径下找到。

然后配置编译脚本

Windows用户,在make.bat中加入:

if "%1" == "pdf" (
  %SPHINXBUILD% -b pdf %ALLSPHINXOPTS% %BUILDDIR%/pdf
  if errorlevel 1 exit /b 1
  echo.
  echo.Build finished. The pdf files are in %BUILDDIR%/pdf.
  goto end
)

类Unix用户修改Makefile:

pdf:
  $(SPHINXBUILD) -b pdf $(ALLSPHINXOPTS) $(BUILDDIR)/pdf
  @echo
  @echo "Build finished. The PDF files are in _build/pdf."

输出PDF

然后一句:

make pdf

就能输出PDF了。

解决findfonts.py:249 Unknown font:

这应该是由于pdf_font_path配置有误造成的,事实上,我确定配置无误rst2pdf还是找不到字体文件,于是我修改了X:\Program Files (x86)\Python27\Lib\site-packages\rst2pdf\findfonts.py第236行,在

fontfile = get_nt_fname(fname)

后面加了一句:

fontfile = 'C:\\Windows\\Fonts\\simsun.ttc'

强行解决问题。

解决rst2pdf输出PDF为空白文档

事实上,在字体正常的情况下,我发现输出的PDF依然是空白的:

使用rst2pdf实现将sphinx生成PDF

在使用二分法排除rst文件中的问题后,我发现这是由于PDF开头的目录造成的。当目录超出一页时就会发生这种情况,我倾向于认为这是rst2pdf的一个bug。

解决方法是将pdf_toc_depth调小一点,或者干脆不生成目录,pdf_use_toc = False。

PDF效果

于是再次重试,可以生成漂亮的PDF了:

使用rst2pdf实现将sphinx生成PDF

相关链接:

http://sphinx-users.jp/cookbook/pdf/rst2pdf.html

http://ralsina.me/static/manual.pdf

http://www.typemylife.com/sphinx-restructuredtext-pdf-generation-with-rst2pdf/

Python 相关文章推荐
python+Splinter实现12306抢票功能
Sep 25 Python
python 画三维图像 曲面图和散点图的示例
Dec 29 Python
Python3中lambda表达式与函数式编程讲解
Jan 14 Python
TensorFlow车牌识别完整版代码(含车牌数据集)
Aug 05 Python
python获取指定日期范围内的每一天,每个月,每季度的方法
Aug 08 Python
python读取与处理netcdf数据方式
Feb 14 Python
使用python创建生成动态链接库dll的方法
May 09 Python
keras绘制acc和loss曲线图实例
Jun 15 Python
Python 如何在字符串中插入变量
Aug 01 Python
Python接收手机短信的代码整理
Aug 02 Python
Python批量获取并保存手机号归属地和运营商的示例
Oct 09 Python
Python实现Hash算法
Mar 18 Python
python监控文件或目录变化
Jun 07 #Python
浅析Python中的多条件排序实现
Jun 07 #Python
Python卸载模块的方法汇总
Jun 07 #Python
Python运行报错UnicodeDecodeError的解决方法
Jun 07 #Python
PyCharm使用教程之搭建Python开发环境
Jun 07 #Python
Python使用Pycrypto库进行RSA加密的方法详解
Jun 06 #Python
Python的Flask框架应用调用Redis队列数据的方法
Jun 06 #Python
You might like
一个简单的自动发送邮件系统(二)
2006/10/09 PHP
Zend 输出产生XML解析错误
2009/03/03 PHP
mysqli_set_charset和SET NAMES使用抉择及优劣分析
2013/01/13 PHP
PHP删除目录及目录下所有文件的方法详解
2013/06/06 PHP
处理单名多值表单的详解
2013/06/08 PHP
解析PHP SPL标准库的用法(遍历目录,查找固定条件的文件)
2013/06/18 PHP
PHP中使用Imagick实现各种图片效果实例
2015/01/21 PHP
PHP根据图片色界在不同位置加水印的方法
2015/07/01 PHP
PHP设计模式之命令模式示例详解
2020/12/20 PHP
Javascript的闭包
2009/12/31 Javascript
js实现上传图片之上传前预览图片
2013/03/25 Javascript
JS截取url中问号后面参数的值信息
2014/04/29 Javascript
浅谈JSON和JSONP区别及jQuery的ajax jsonp的使用
2014/11/23 Javascript
js控制输入框获得和失去焦点时状态显示的方法
2015/01/30 Javascript
《JavaScript高级编程》学习笔记之object和array引用类型
2015/11/01 Javascript
AngularJS自定义插件实现网站用户引导功能示例
2016/11/07 Javascript
详解如何使用Vue2做服务端渲染
2017/03/29 Javascript
JS实现多级菜单中当前菜单不随页面跳转样式而发生变化
2017/05/30 Javascript
SelectPage v2.4 发布新增纯下拉列表和关闭分页功能
2017/09/07 Javascript
AngularJS中下拉框的基本用法示例
2017/10/11 Javascript
原生js实现商品筛选功能
2019/10/28 Javascript
解决vue 使用axios.all()方法发起多个请求控制台报错的问题
2020/11/09 Javascript
[02:37]2015国际邀请赛选手档案—LGD.Xiao8
2015/07/28 DOTA
python基于Tkinter库实现简单文本编辑器实例
2015/05/05 Python
pygame游戏之旅 添加游戏暂停功能
2018/11/21 Python
Python3.5以上版本lxml导入etree报错的解决方案
2019/06/26 Python
CSS3制作酷炫的条纹背景
2017/11/09 HTML / CSS
StubHub巴西:购买和出售您的门票
2016/07/22 全球购物
斯巴达比赛商店:Spartan Race
2019/01/08 全球购物
入职担保书范文
2014/05/21 职场文书
物联网工程专业推荐信
2014/09/08 职场文书
2014年安全生产工作总结
2014/11/13 职场文书
初中开学典礼新闻稿
2015/07/17 职场文书
超级实用的公文标题大全!
2019/07/19 职场文书
JavaScript中时间格式化新思路toLocaleString()
2021/11/07 Javascript
【海涛解说】暗牧也疯狂,牛蛙成配角
2022/04/01 DOTA