记一次Python调试: Readme2TeX

 

${\rm \LaTeX}$环境整理”后遗症”: Readme2TeX不能用了。本文记录本次debug过程。

前言

Readme2TeX是由Lee Gao编写的一款python模块, 可使GitHub的Readme支持${\rm \LaTeX}$渲染。具体的用法可以参见其repo或参考这里。时隔有段时间后发现该工具不可用, 而这期间的变化是卸载了CTeX套装, 改装了MiKTeX

错误定位

使用该工具的错误提示如下:

(readme2tex) D:\Github>python -m readme2tex --nocdn --output README.md READOTHER.md
Traceback (most recent call last):
  File "C:\Users\yuze\Anaconda3\envs\readme2tex\lib\runpy.py", line 193, in _run_module_as_main
    "__main__", mod_spec)
  File "C:\Users\yuze\Anaconda3\envs\readme2tex\lib\runpy.py", line 85, in _run_code
    exec(code, run_globals)
  File "C:\Users\yuze\Anaconda3\envs\readme2tex\lib\site-packages\readme2tex\__main__.py", line 162, in <module>
    args.bustcache)
  File "C:\Users\yuze\Anaconda3\envs\readme2tex\lib\site-packages\readme2tex\render.py", line 177, in render
    xml = (ET.fromstring(svg))
  File "C:\Users\yuze\Anaconda3\envs\readme2tex\lib\xml\etree\ElementTree.py", line 1315, in XML
    return parser.close()
xml.etree.ElementTree.ParseError: no element found: line 1, column 0

通过调试, 定位到错误发生的关键点在于render.py177行, 即: xml = (ET.fromstring(svg)), 而上下文代码如下:

svg, dvi, name = rendertex(engine, equation, packages, temp_dir, block)
svg = svg.decode('utf-8')

xml = (ET.fromstring(svg))

由于svg为空字符, 导致了后续错误, 而造成svg为空字符的原因在于rendertex函数中的这一部分:

dvi = os.path.join(temp_dir, name + '.dvi')
svg = check_output(
    ['dvisvgm', '-v0', '-a', '-n', '-s', dvi])
return svg, dvi, name

此处通过check_output函数调用了外部指令并捕获指令执行的输出结果传递给变量svg, 该外部指令如下:

dvisvgm -v0 -a -n -s [dvi]

通过查看dvisvgm的用法, 此处-v0设置verbose等级为0, 导致报错信息被隐藏, 设置-v1后, 会提示如下的错误信息:

ERROR: MiKTeX session could not be initialized

Google该错误提醒查询到如下解释1, 2:

dvisvgm needs access to the MiKTeX COM interface which seems not to be available on my system – probably because I installed miktex as single user without admin rights.

错误原因在于dvisvgm会调用MiKTeX的COM接口, 而由于此前卸载了CTeX, 改装了MiKTeX未赋予其管理员权限导致dvisvgm无法调用。解决方案为2, 3: 以管理员权限在cmd中执行如下指令:

mpm --register-components --verbose

小结

Readme2TeX的执行流程如下:

graph LR;
A[*.tex]  --> | LaTeX引擎 | B(*.dvi)
B --> | dvisvgm | C[*.svg]

错误出在dvi->svg这一环, 注册MiKTeX组件使dvisvgm可以调用即可。

调试Python module

分别通过PyCharm和VSCode进行调试。两者的module调试功能都比较直观。

PyCharm

PyCharm的module调试步骤如下:

Run ➡ Edit Configurations… ➡ 点击”+” ➡ 选择Python ➡ “Script path:“下拉修改为”Module name” ➡ 填入需要调试的module名称 ➡ Parameters键入执行module需要的参数(如果有) ➡ 选择Working directory(如果有文件交互) ➡ Apply ➡ OK

pycharm-debug图1: PyCharm 调试Python Module

VSCode

目前VSCode对Python的支持已经相当完善, 有了官方Python插件加持, VSCode是一款优异的Python IDE。不同于PyCharm提供的GUI界面, VSCode的调试通过创建launch.json进行配置, 同样直观, 其配置文件类似如下:

{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Python: 模块",
            "type": "python",
            "request": "launch",
            "module": "readme2tex",
            "args": ["--nocdn", "--rerender",  "--usepackage", "tikz", "--output", "README.md", "READOTHER.md"]
        }
    ]
}

其中, args负责配置执行module需要添加的参数, 将命令行以空格分隔的参数, 逐一填入字符串list即可。

vsc-debug图2: VSCode 调试Python Module

Tips

调试module时需要注意Python项目的根目录选择(即: .idea.vscode所在目录)。以readme2tex为例, 其repo目录结构如下, 其中readme2tex模块的主体为子级readme2tex。因此在调试该module时, 需要将根目录设置为父级readme2tex, 如此, IDE才可以识别到需要调试的module。

📦readme2tex        # 父级
 ┣ 📂readme2tex     # 子级
 ┃ ┣ 📜render.py
 ┃ ┣ 📜__init__.py
 ┃ ┗ 📜__main__.py
 ┗ ...