在转换chm、markdown、epub等文件中遇到大量问题后,我决定仔读一遍Calibre用户手册,并结合代码分析。
注意:本次我会使用chrome自带的翻译功能。
首先放上我另一篇文章开源软件calibre源码研究与程序编译(编译只能在linux下进行,未成功)
在这篇里,我讨论了如何设置Calibre的开发环境。
这里,再次,首先下载源码包。这次我使用了git,所以为了以防万一,我切换版本到4.12.0。
经过一番配置,我再次获得了Hello World。
代码布局
所有口径的python代码都在calibre软件包中。该软件包包含以下主要子软件包
设备-所有设备驱动程序。只需查看一些内置驱动程序即可了解它们的工作原理。
有关详细信息,请参见:devices.interface定义了设备驱动程序支持的接口,devices.usbms并定义了连接到USBMS设备的通用驱动程序。口径中所有基于USBMS的驱动程序均继承自该驱动程序。
电子书-所有电子书转换/元数据代码。一个很好的起点是calibre.ebooks.conversion.cli为电子书转换命令提供动力的模块。转换过程通过进行控制conversion.plumber。格式无关的代码都在中ebooks.oeb,而格式相关的代码在中ebooks.format_name。读取,写入和下载元数据全在其中 ebooks.metadata
转换发生在管道中,有关管道的结构,请参见简介。管道包括输入插件,各种转换和输出插件。构造和驱动管道的代码在中plumber.py。管道可处理像未压缩的epub之类的电子书,具有清单,书脊,目录,指南,html内容等。管理此表示的类是OEBBook in ebooks.oeb.base。转换过程中应用于该书的各种转换都存在于中oeb/transforms/*.py。输入和输出插件都位于中conversion/plugins/*.py。
电子书编辑使用其他容器对象进行。电子书编辑工具的API文档中对此进行了记录。
db-数据库后端。有关口径库的接口,请参见数据库接口的API文档。内容服务器:srv是口径的内容服务器。
gui2-图形用户界面。GUI初始化发生在gui2.main和中gui2.ui。电子书阅读器在中gui2.viewer。电子书编辑器在中gui2.tweak_book。
如果要查找所有各种口径可执行文件的入口点,请查看linux.py中的entry_points结构。
如果您需要帮助来理解代码,请在开发论坛中发帖 ,您很可能会从calibre的众多开发人员之一获得帮助。
我又试了试使用交互式Python解释器
这里我出了一点问题。
from calibre import ipython
ipython(locals())
直接添加在最开始无效
但是仔细研究之后,我们是在calibre这个包的__init__.py
,ipython是定义在这个文件里的一个函数。
所以调用以上语句,只需要移到最后即可以生效。
并且在这个文件里,其实直接调用ipython(locals())
就可以了。
但是调用了之后,大家会发现,只是进入了一个shell。并不是ipython
为何呢?
在查询论坛之后,我找的这样一个帖子:
ipython somehow not working?
按里面的说法,calibre已经不再包含ipython
使用相应代码是直接进入python shell。当然也可以用。
但是如果想要使用ipython的话,应该怎么做那?
首先,假如你电脑上没有python2.7的话,下载python2.7
然后pip install ipython
安装好了以后,使用ipython2命令打开ipython 5.9
这是python2下支持的最高版本。
输入
import sys
print sys.path
可以得到如下类型的内容
['', 'D:\\Program Files\\Python\\Python27\\Scripts\\ipython2.exe', ...]
把
import sys
sys.path.extend([the path you got])
import IPython
from IPython.config.loader import Config
IPython.embed(user_ns=locals())
输入之前
from calibre import ipython
ipython(locals())
的位置就可以运行ipython。
从方便的角度看,我建议修改ipyhon函数。
def ipython(user_ns=None):
import sys
sys.path.extend([the path you got])
import IPython
from IPython.config.loader import Config
# and then put to a suitable place in tour code this:
IPython.embed(user_ns=user_ns)
'''
from calibre.utils.ipython import ipython
ipython(user_ns=user_ns)
'''
如上,这样就可以依然使用
from calibre import ipython
ipython(locals())
来使用ipython了。
但是我们要来看一看,这样用,与它的
from calibre.utils.ipython import ipython
ipython(user_ns=user_ns)
有什么区别呢?
它调用了calibre.utils.ipython,我们来看一看。
这个文件在源码包的calibre\utils\ipython.py里。
def ipython(user_ns=None):
os.environ['IPYTHONDIR'] = ipydir
try:
from IPython.terminal.embed import InteractiveShellEmbed
from traitlets.config.loader import Config
from IPython.terminal.prompts import Prompts, Token
except ImportError:
return simple_repl(user_ns=user_ns)
class CustomPrompt(Prompts):
def in_prompt_tokens(self, cli=None):
return [
(Token.Prompt, 'calibre['),
(Token.PromptNum, get_version()),
(Token.Prompt, ']> '),
]
def out_prompt_tokens(self):
return []
defns = {'os':os, 're':re, 'sys':sys}
defns.update(user_ns or {})
c = Config()
user_conf = os.path.expanduser('~/.ipython/profile_default/ipython_config.py')
if os.path.exists(user_conf):
exec_path(user_conf, {'get_config': lambda: c})
c.TerminalInteractiveShell.prompts_class = CustomPrompt
c.InteractiveShellApp.exec_lines = [
'from __future__ import division, absolute_import, unicode_literals, print_function',
]
c.TerminalInteractiveShell.confirm_exit = False
c.TerminalInteractiveShell.banner1 = BANNER
c.BaseIPythonApplication.ipython_dir = ipydir
c.InteractiveShell.separate_in = ''
c.InteractiveShell.separate_out = ''
c.InteractiveShell.separate_out2 = ''
ipshell = InteractiveShellEmbed.instance(config=c, user_ns=user_ns)
ipshell()
函数如上
老实说我看不懂【摊手】
不过没事,可以debug就行。
首先检查走的是那条路。
啊,不幸的是,走的是
except ImportError:
return simple_repl(user_ns=user_ns)
那么一定前面出错了,检查一下。
try:
from IPython.terminal.embed import InteractiveShellEmbed
from traitlets.config.loader import Config
from IPython.terminal.prompts import Prompts, Token
这里,全部导入失败了。
然而测试了一下,这些都能导入的啊?问题在哪里呢?
测试了一遍,无法导入ipython。
那么把sys.path.extend([the path you got])加到这个文件开头。
问题解决了!
现在,我们可以用ipython了。