执行预处理器
仅查看代码单元格,因此您的标记单元格完全未受影响。要进行标记处理,您需要Python Markdown预处理器,正如您所述。
不幸的是,Python Markdown预处理器系统仅在实时笔记本中执行代码,它通过
修改涉及呈现单元格的javascript来完成。修改将执行代码片段的结果存储在单元格元数据中。
PyMarkdownPreprocessor
类(在
pre_pymarkdown.py中)旨在与nbconvert一起使用,nbconvert操作的是先在实时笔记本设置中呈现过的笔记本。它处理标记单元格,将
{{}}
模式替换为元数据中存储的值。
在您的情况下,您没有实时笔记本元数据。我曾经遇到过类似的问题,并通过编写自己的执行预处理器来解决它,该预处理器还包括处理markdown单元格的逻辑:
from nbconvert.preprocessors import ExecutePreprocessor, Preprocessor
import nbformat, nbconvert
from textwrap import dedent
class ExecuteCodeMarkdownPreprocessor(ExecutePreprocessor):
def __init__(self, **kw):
self.sections = {'default': True}
self.EmptyCell = nbformat.v4.nbbase.new_raw_cell("")
return super().__init__(**kw)
def preprocess_cell(self, cell, resources, cell_index):
"""
Executes a single code cell. See base.py for details.
To execute all cells see :meth:`preprocess`.
"""
if cell.cell_type not in ['code','markdown']:
return cell, resources
if cell.cell_type == 'code':
return self.preprocess_code_cell(cell, resources, cell_index)
elif cell.cell_type == 'markdown':
return self.preprocess_markdown_cell(cell, resources, cell_index)
else:
return cell, resources
def preprocess_code_cell(self, cell, resources, cell_index):
''' Process code cell.
'''
outputs = self.run_cell(cell)
cell.outputs = outputs
if not self.allow_errors:
for out in outputs:
if out.output_type == 'error':
pattern = u"""\
An error occurred while executing the following cell:
------------------
{cell.source}
------------------
{out.ename}: {out.evalue}
"""
msg = dedent(pattern).format(out=out, cell=cell)
raise nbconvert.preprocessors.execute.CellExecutionError(msg)
return cell, resources
def preprocess_markdown_cell(self, cell, resources, cell_index):
cell['metadata']['variables'] = {}
for m in re.finditer("{{(.*?)}}", cell.source):
fakecell = nbformat.v4.nbbase.new_code_cell(m.group(1))
fakecell, resources = self.preprocess_code_cell(fakecell, resources, cell_index)
for output in fakecell.outputs:
html = self.convert_output_to_html(output)
if html is not None:
cell['metadata']['variables'][fakecell.source] = html
break
return cell, resources
def convert_output_to_html(self, output):
'''Convert IOpub output to HTML
See https://github.com/ipython-contrib/IPython-notebook-extensions/blob/master/nbextensions/usability/python-markdown/main.js
'''
if output['output_type'] == 'error':
text = '**' + output.ename + '**: ' + output.evalue;
return text
elif output.output_type == 'execute_result' or output.output_type == 'display_data':
data = output.data
if 'text/latex' in data:
html = data['text/latex']
return html
elif 'image/svg+xml' in data:
return None
elif 'image/jpeg' in data:
jpeg = data['image/jpeg']
html = '<img src="data:image/jpeg;base64,' + jpeg + '"/>'
return html
elif 'image/png' in data:
png = data['image/png']
html = '<img src="data:image/png;base64,' + png + '"/>'
return html
elif 'text/markdown' in data:
text = data['text/markdown']
return text
elif 'text/html' in data:
html = data['text/html']
return html
elif 'text/plain' in data:
text = data['text/plain']
text = re.sub(r'<p>([\s\S]*?)<\/p>', r'\1', text)
text = re.sub(r"'([\s\S]*?)'",r'\1', text)
return text
else:
return None
else:
return None
您可以使用类似于您发布的代码的逻辑处理笔记本电脑:
import nbformat
from nbconvert.preprocessors import ExecutePreprocessor
import ExecuteCodeMarkdownPreprocessor
import PyMarkdownPreprocessor
with open('report.ipynb') as f:
nb = nbformat.read(f, as_version=4)
ep = ExecuteCodeMarkdownPreprocessor(timeout=600, kernel_name='python3')
ep.preprocess(nb, {})
pymk = PyMarkdownPreprocessor()
pymk.preprocess(nb, {})
with open('report_executed.ipynb', 'wt') as f:
nbformat.write(nb, f)
请注意,通过包含Python Markdown预处理,您得到的笔记本文件将不再在Markdown单元格中具有
{{}} 语法-Markdown将具有静态内容。如果结果笔记本的接收者更改代码并再次执行,则Markdown将不会更新。但是,如果您导出为不同格式(例如HTML),则确实需要使用静态内容替换 {{}} 语法。