【问题标题】:Simple way to choose which cells to run in ipython notebook during run all在全部运行期间选择在 ipython 笔记本中运行哪些单元的简单方法
【发布时间】:2014-10-21 19:29:25
【问题描述】:

我有一个 ipython 笔记本,它在数据处理例程中运行多个步骤,并在此过程中将信息保存在文件中。这样,在开发我的代码时(主要在一个单独的 .py 模块中),我可以跳到并运行各个步骤。我想设置它以便我可以Cell->run all 但只让它执行某些很容易选择的选定步骤。例如,我想像这样定义我想在 dict 中运行的步骤:

process = {
    'load files':False,
    'generate interactions list':False,
    'random walk':True,
    'dereference walk':True,
    'reduce walk':True,
    'generate output':True
}

然后这些步骤将基于此 dict 运行。顺便说一句,每个步骤都包含多个单元格。

我认为%macro 不是我想要的,因为无论何时我更改任何内容或重新启动内核,我都必须重新定义宏,并更改单元格编号。

有没有类似%skip%skipto 的魔法或类似的东西?或者也许是一个干净的方式放在单元格的开头,if process[<current step>]: %dont_run_rest_of_cell

【问题讨论】:

  • 我也有同样的需求——我使用笔记本作为自动生成报告的模板。我希望能够根据某些条件定义我的笔记本的哪些部分被执行,例如是否存在某个输入文件(即,如果提供了这个文件,则运行接下来的 6 个单元格)。这个想法让我想起了 C 系列语言中的#define、#ifdef 编译器宏。

标签: ipython ipython-notebook


【解决方案1】:

您可以在自定义内核扩展的帮助下创建自己的跳跃魔法。

skip_kernel_extension.py

def skip(line, cell=None):
    '''Skips execution of the current line/cell if line evaluates to True.'''
    if eval(line):
        return

    get_ipython().ex(cell)

def load_ipython_extension(shell):
    '''Registers the skip magic when the extension loads.'''
    shell.register_magic_function(skip, 'line_cell')

def unload_ipython_extension(shell):
    '''Unregisters the skip magic when the extension unloads.'''
    del shell.magics_manager.magics['cell']['skip']

在你的笔记本中加载扩展:

%load_ext skip_kernel_extension

在要跳过的单元格中运行跳过魔法命令:

%%skip True  #skips cell
%%skip False #won't skip

您可以使用变量来决定是否应该使用 $: 跳过单元格

should_skip = True
%%skip $should_skip

【讨论】:

  • 很酷,但是在哪里放置“自定义内核扩展”?
  • @Arthur:你可以把你的扩展模块放在任何你想要的地方,只要它们可以被 Python 的标准导入机制导入。但是,为了方便编写扩展,您还可以将扩展放在 IPython 目录中的 extensions/ 中。此目录会自动添加到 sys.path。
  • 而不是 get_ipython().ex(cell) 更好的 get_ipython().run_cell(cell)
【解决方案2】:

如果您使用 nbconvert 执行笔记本,则可以编写一个自定义预处理器,查看单元元数据以了解要执行哪些单元。

class MyExecutePreprocessor(nbconvert.preprocessors.ExecutePreprocessor):

    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`.

        Checks cell.metadata for 'execute' key. If set, and maps to False, 
          the cell is not executed.
        """

        if not cell.metadata.get('execute', True):
            # Don't execute this cell in output
            return cell, resources

        return super().preprocess_cell(cell, resources, cell_index)

通过编辑单元格元数据,您可以指定是否应执行该单元格。

您可以通过将主词典添加到笔记本元数据中来获得更多乐趣。这看起来像您示例中的字典,将部分映射到布尔值,指定是否调用该部分。

然后,在您的单元元数据中,您可以使用“部分”关键字映射到笔记本元数据中的部分 ID。

在执行 nbconvert 时,您可以告诉它使用您的预处理器。

更多信息请参见the docs on Notebook preprocessors

【讨论】:

  • 我在回答这个相关问题时添加了更多细节:stackoverflow.com/questions/33517900/…
  • 谢谢@Gordon Bean。编辑单元元数据最方便的方法是什么?有什么方法可以通过 Jupyter 笔记本中的命令来实现吗?
  • @colorlessgreenidea - 您可以通过笔记本编辑器编辑元数据。我不确定是否有一种方法可以使用命令编辑元数据(尽管这对 SO 来说是一个很好的问题;)。
【解决方案3】:

我是 Jupyter Notebook 的新手,我很喜欢它。我之前听说过 IPython,但直到最近的一份咨询工作才认真研究它。

我的同事向我展示的一个禁用块执行的技巧是将它们从“代码”类型更改为“原始 NBConvert”类型。通过这种方式,我将诊断块洒在我的笔记本上,但只有在我希望它们运行时才打开它们(将它们设为“代码”)。

此方法在脚本中不能完全动态选择,但可能适合某些需求。

【讨论】:

    【解决方案4】:

    除了上面 Robbe 所说的话(我不能评论,因为我是新人),如果您不想创建一个您可能会忘记的自定义扩展,您可以在您的第一个单元格中执行以下操作:

    def skip(line, cell=None):
        '''Skips execution of the current line/cell if line evaluates to True.'''
        if eval(line):
            return
    
        get_ipython().ex(cell)
    
    def load_ipython_extension(shell):
        '''Registers the skip magic when the extension loads.'''
        shell.register_magic_function(skip, 'line_cell')
    
    def unload_ipython_extension(shell):
        '''Unregisters the skip magic when the extension unloads.'''
        del shell.magics_manager.magics['cell']['skip']
        
        
    load_ipython_extension(get_ipython())
    

    【讨论】:

    • 而不是 get_ipython().ex(cell) 更好的 get_ipython().run_cell(cell)
    【解决方案5】:

    显式总是比隐式好。简单胜于复杂。那么为什么不使用普通的python呢?

    每一步只有一个单元格,您可以这样做:

    if process['load files']:
        load_files()
        do_something()
    

    if process['generate interactions list']:
        do_something_else()
    

    如果您想在跳过特定步骤时停止执行,您可以使用:

    if not process['reduce walk']:
        stop
    else:
        reduce_walk()
        ...
    

    stop 不是命令,所以在使用 Cell -> Run all 时会产生异常并停止执行。

    您还可以执行以下条件步骤:

    if process['reduce walk'] and process['save output']:
        save_results()
        ...
    

    但是,根据经验,我不会提出比这更复杂的条件。

    【讨论】:

      【解决方案6】:

      您可以在元数据中使用 nbconvert 和 tags 选项: 就我而言,我编辑了单元格元数据:

      {
          "deletable": true,
          "colab_type": "code",
          "id": "W9i6oektpgld",
          "tags": [
              "skip"
          ],
          "colab": {},
          "editable": true
      }
      

      创建一个preprocess.py 文件。

      from nbconvert.preprocessors import Preprocessor
      
      class RemoveCellsWithNoTags(Preprocessor):
          def preprocess(self, notebook, resources):
              executable_cells = []
              for cell in notebook.cells:
                  if cell.metadata.get('tags'):
                      if "skip" in cell.metadata.get('tags'):
                          continue
                  executable_cells.append(cell)
              notebook.cells = executable_cells
              return notebook, resources
      

      然后导出笔记本:

      jupyter nbconvert --Exporter.preprocessors=[\"preprocess.RemoveCellsWithNoTags\"] --ClearOutputPreprocessor.enabled=True --to notebook --output=getting-started-keras-test getting-started-keras.ipynb
      

      【讨论】:

        【解决方案7】:

        或者从另一个角度来看,您可以跳过不想运行的单元格(即通过在需要跳过的单元格的第一行添加以下代码)。

        %%script echo skipping
        

        【讨论】:

          猜你喜欢
          • 2015-12-10
          • 2015-11-11
          • 1970-01-01
          • 2013-10-19
          • 1970-01-01
          • 2016-06-16
          • 2020-12-21
          • 2014-09-02
          相关资源
          最近更新 更多