2016-03-04 79 views
3

我有一個Jupyter筆記本,其包括像這樣在降價細胞蟒變量直列降價:執行一個Jupyter筆記本包括與nbconvert

碼單元:

x = 10 

降價細胞:

The value of x is {{x}}. 

IPython-notebook-extension Python Markdown允許我動態顯示這些變量,如果我在筆記本中使用shift-enter執行降格單元格。

降價細胞:

The value of x is 10. 

我想以編程方式執行所有電池在筆記本電腦和使用這樣的事情將它們保存到一個新的筆記本:

import nbformat 
from nbconvert.preprocessors import ExecutePreprocessor 

with open('report.ipynb') as f: 
    nb = nbformat.read(f, as_version=4) 
     ep = ExecutePreprocessor(timeout=600, kernel_name='python3') 
     ep.preprocess(nb, {}) 
with open('report_executed.ipynb', 'wt') as f: 
    nbformat.write(nb, f) 

這將執行代碼細胞但不是降價單元格。他們仍然是這樣的:

The value of x is {{x}}. 

我認爲問題是筆記本電腦不受信任。有沒有辦法告訴ExecutePreprocessor信任筆記本?是否有另一種方式來編程執行包含降格單元格中的python變量的筆記本?

+1

將變量放入降價單元的筆記本擴展可能不會影響使用ExecutePreprocessor運行筆記本。 –

回答

3

ExecutePreprocessor only looks at code cells,所以你的減價單元格是完全不變的。如您所述,要進行降價處理,您需要使用Python Markdown預處理器。

不幸的是,Python Markdown預處理器系統僅執行實時筆記本中的代碼,它在modifying the javascript involved with rendering cells中執行代碼。修改將代碼片斷的執行結果存儲在單元元數據中。

PyMarkdownPreprocessor類(pre_pymarkdown.py)設計用於在筆記本電腦上運行的nbconvert,該筆記本電腦已在現場筆記本電腦設置中首先渲染。它處理降價單元格,用存儲在元數據中的值替換{{}}模式。

但是,在您的情況下,您沒有實時筆記本元數據。我也有類似的問題,我寫我自己的執行預處理器,其中還包括邏輯來處理降價細胞解決了這個問題:

from nbconvert.preprocessors import ExecutePreprocessor, Preprocessor 
import nbformat, nbconvert 
from textwrap import dedent 

class ExecuteCodeMarkdownPreprocessor(ExecutePreprocessor): 

    def __init__(self, **kw): 
     self.sections = {'default': True} # maps section ID to true or false 
     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': 
      # Do code stuff 
      return self.preprocess_code_cell(cell, resources, cell_index) 

     elif cell.cell_type == 'markdown': 
      # Do markdown stuff 
      return self.preprocess_markdown_cell(cell, resources, cell_index) 
     else: 
      # Don't do anything 
      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): 
     # Find and execute snippets of code 
     cell['metadata']['variables'] = {} 
     for m in re.finditer("{{(.*?)}}", cell.source): 
      # Execute code 
      fakecell = nbformat.v4.nbbase.new_code_cell(m.group(1)) 
      fakecell, resources = self.preprocess_code_cell(fakecell, resources, cell_index) 

      # Output found in cell.outputs 
      # Put output in cell['metadata']['variables'] 
      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: 
       # Not supported 
       #var svg = ul['image/svg+xml']; 
       #/* embed SVG in an <img> tag, still get eaten by sanitizer... */ 
       #svg = btoa(svg); 
       #html = '<img src="data:image/svg+xml;base64,' + svg + '"/>'; 
       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'] 
       # Strip <p> and </p> tags 
       # Strip quotes 
       # html.match(/<p>([\s\S]*?)<\/p>/)[1] 
       text = re.sub(r'<p>([\s\S]*?)<\/p>', r'\1', text) 
       text = re.sub(r"'([\s\S]*?)'",r'\1', text) 
       return text 
      else: 
      # Some tag we don't support 
       return None 
     else: 
      return None 

然後,您可以處理你與類似於您發佈的代碼邏輯筆記本:

import nbformat 
from nbconvert.preprocessors import ExecutePreprocessor 
import ExecuteCodeMarkdownPreprocessor # from wherever you put it 
import PyMarkdownPreprocessor # from pre_pymarkdown.py 

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預處理,您的結果筆記本文件在降格單元格中將不再具有{{}}語法 - 降格將具有靜態內容。如果生成筆記本的收件人更改了代碼並再次執行,則減價不會更新。但是,如果要導出爲其他格式(例如HTML),那麼您確實需要用靜態內容替換{{}}語法。