这是我写的一个小脚本。它分裂单一 *.ipynb 文件并将其转换为多个 *.tex 文件。
*.ipynb
*.tex
用法是:
main.py
python main.py init
main.tex
style_ipython_custom.tplx
#latex:tag_a
#latex:tag_b
*.py
python main.py path/to/your.ipynb
tag_a.tex
tag_b.tex
\input{tag_a.tex}
\input{tag_b.tex}
pdflatex main.tex
main.pdf
这个脚本背后的想法:
使用默认值从jupyter笔记本转换为LaTex nbconvert.LatexExporter 生成包含宏定义的完整LaTex文件。使用它来转换每个单元格可能会创建大型LaTex文件。为避免此问题,脚本首先创建 main.tex 它只有宏定义,然后将每个单元格转换为没有宏定义的LaTex文件。这可以使用稍微修改的自定义模板文件来完成 style_ipython.tplx
nbconvert.LatexExporter
style_ipython.tplx
标记或标记单元格可能是使用单元格元数据完成的,但我找不到如何在VSCode python插件中设置它( 问题 ),所以相反它用正则表达式模式扫描每个单元格的源 ^#latex:(.*) ,并在将其转换为LaTex文件之前将其删除。
^#latex:(.*)
资源:
import sys import re import os from collections import defaultdict import nbformat from nbconvert import LatexExporter, exporters OUTPUT_FILES_DIR = './images' CUSTOM_TEMPLATE = 'style_ipython_custom.tplx' MAIN_TEX = 'main.tex' def create_main(): # creates `main.tex` which only has macro definition latex_exporter = LatexExporter() book = nbformat.v4.new_notebook() book.cells.append( nbformat.v4.new_raw_cell(r'\input{__your_input__here.tex}')) (body, _) = latex_exporter.from_notebook_node(book) with open(MAIN_TEX, 'x') as fout: fout.write(body) print("created:", MAIN_TEX) def init(): create_main() latex_exporter = LatexExporter() # copy `style_ipython.tplx` in `nbconvert.exporters` module to current directory, # and modify it so that it does not contain macro definition tmpl_path = os.path.join( os.path.dirname(exporters.__file__), latex_exporter.default_template_path) src = os.path.join(tmpl_path, 'style_ipython.tplx') target = CUSTOM_TEMPLATE with open(src) as fsrc: with open(target, 'w') as ftarget: for line in fsrc: # replace the line so than it does not contain macro definition if line == "((*- extends 'base.tplx' -*))\n": line = "((*- extends 'document_contents.tplx' -*))\n" ftarget.write(line) print("created:", CUSTOM_TEMPLATE) def group_cells(note): # scan the cell source for tag with regexp `^#latex:(.*)` # if sames tags are found group it to same list pattern = re.compile(r'^#latex:(.*?)$(\n?)', re.M) group = defaultdict(list) for num, cell in enumerate(note.cells): m = pattern.search(cell.source) if m: tag = m.group(1).strip() # remove the line which contains tag cell.source = cell.source[:m.start(0)] + cell.source[m.end(0):] group[tag].append(cell) else: print("tag not found in cell number {}. ignore".format(num + 1)) return group def doit(): with open(sys.argv[1]) as f: note = nbformat.read(f, as_version=4) group = group_cells(note) latex_exporter = LatexExporter() # use the template which does not contain LaTex macro definition latex_exporter.template_file = CUSTOM_TEMPLATE try: os.mkdir(OUTPUT_FILES_DIR) except FileExistsError: pass for (tag, g) in group.items(): book = nbformat.v4.new_notebook() book.cells.extend(g) # unique_key will be prefix of image (body, resources) = latex_exporter.from_notebook_node( book, resources={ 'output_files_dir': OUTPUT_FILES_DIR, 'unique_key': tag }) ofile = tag + '.tex' with open(ofile, 'w') as fout: fout.write(body) print("created:", ofile) # the image data which is embedded as base64 in notebook # will be decoded and returned in `resources`, so write it to file for filename, data in resources.get('outputs', {}).items(): with open(filename, 'wb') as fres: fres.write(data) print("created:", filename) if len(sys.argv) <= 1: print("USAGE: this_script [init|yourfile.ipynb]") elif sys.argv[1] == "init": init() else: doit()
我会用 bookdown 在同一文档中包含测试和源代码(为方便起见,将其拆分为多个文件)。此软件包源自R世界,但也可与其他语言一起使用。这是一个非常简单的例子:
--- output: bookdown::pdf_document2 --- ```{r setup, include=FALSE} knitr::opts_chunk$set(echo = TRUE) ``` # Setup data First we define some varialbes with data. ```{python data} bob = ['Bob Smith', 42, 30000, 'software'] sue = ['Sue Jones', 45, 40000, 'music'] ``` # Output data then we output some of the data. ```{python output} bob[0], sue[2] ``` # Reference code block Finally lets repeate the code block without evaluating it. ```{python, ref.label="output", eval = FALSE} ```
输出:
Jupyter不允许从笔记本中导出特定单元 - 它只允许您导出整个笔记本。为了尽可能接近理想情况,您需要一个模块化的Jupyter设置:
在LaTeX中,您可以通过导入生成的.tex文件
\输入{filname.tex}
如果要将较小的笔记本导入主笔记本的单元格中,可以通过以下方式执行此操作(请参阅magic命令 跑 )
%run my_other_notebook.ipynb #or %run 'my notebook with spaces.ipynb'
你也可以通过插入python文件(参见magic命令 加载 )
%load python_file.py
它加载Python文件并允许您在主笔记本中执行它。
您还可以使用小的.py片段,将它们装入小型Jupyter笔记本中,然后在较大的笔记本中运行。
您对VS Code的使用很好,因此,浏览器中的Jupyter可能会更快地进行编辑。
( 所有魔术命令的参考 )