Jupyter Notebook:发生崩溃时如何重新启动上面的所有单元格?

新手上路,请多包涵

问题一:

我将 jupyter 4 与 python 一起使用,我需要我的脚本在发生崩溃时 重新启动上面的所有单元格

这可能吗 ?

问题2:

如果我需要重新启动所有一些单元格,我可以让 python 根据一些单元格 ID 执行它们 吗?然后我可以创建一个单元格 ID 列表,在捕获异常时必须重新执行这些单元格 ID …

原文由 Romain Jouin 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 923
2 个回答

您始终可以使用 Cell > Run All Above 重新启动活动单元格上方的所有单元格。但是当谈到以编程方式和 可靠地 这样做时,我有好消息也有坏消息要告诉您。


让我们排除关于问题 2 的坏消息:否


…至少不是很可靠,因为如果您插入或删除任何其他单元格,单元格的任何 ID 都会改变。

根据 github 上的 通过小部件和条件执行特定单元格

我们没有单元格的 ID,无法以编程方式处理它们。

在同一篇文章中更进一步:

有一些 API 可以运行由数字标识的单元格,但不幸的是,如果您在上面某处插入或删除单元格,数字会发生变化。


现在关于第一个问题的好消息:是的


…但不能 100% 确定它会根据您问题中的详细信息解决您的错误处理需求。但我们稍后会谈到这一点。因为好消息是标题中问题的答案

发生崩溃时如何重新启动上面的所有单元格?

是的, 我们可以!

这个问题的难点(甚至可能是不可能的)部分是将其实现为一种健壮的错误处理方法。如果您只对此感兴趣,请跳至我的回答末尾的 The hard part 部分。现在,让我们继续 easy part 以编程方式运行菜单选项 Cell > Run All (如 Nic Cottrell 的回答中所述)。你有两个选择:

选项 1 - 通过执行一个单元来运行上面的所有单元:

如果您在单元格中插入以下代码片段并运行它,上面的所有单元格都将被执行:

 from IPython.display import Javascript
display(Javascript('IPython.notebook.execute_cells_above()'))

选项 2 - 通过单击按钮运行上面的所有单元格:

如果你在一个单元格中插入下面的代码片段并运行它,当你点击出现的按钮时,上面的所有单元格都会被执行:

片段:

 from IPython.core.display import display, HTML
HTML('''<script> </script> <form action="javascript:IPython.notebook.execute_cells_above()"><input type="submit" id="toggleButton" value="Run all"></form>''')

输出:

在此处输入图像描述


THE HARD PART

那么,我们如何设置它以在发生崩溃时处理错误呢?我不是这方面的专家,但我认为我已经能够进行适合您的设置。但这很可能取决于所讨论的错误类型和您的其余工作流程。

以下示例基于两个不同的错误消息。第一个是 NameError 当您尝试为不存在的变量赋值时发生。这将很有用,因为在错误后重新运行某些单元将需要一个迭代器,该迭代器仅在笔记本完全重新启动时重置,而不是在作为错误处理方法的一部分重新运行单元时重置。只有在重新启动笔记本电脑时重新启动内核时才会出现名称错误。作为错误处理的一部分,值 0 被分配给 x1 。当单元仅重新运行时 x1 将增加 1

第二个错误将作为 您的 错误的代理,并且是每次您尝试 从不存在的列表中删除元素 时发生的 AssignmentError 。这给我们带来了真正的挑战,因为如果您的错误处理程序在每次触发错误时都重新运行上面的所有单元格,您很快就会陷入错误的循环。但是我们将使用一个计数器来处理这个问题,该计数器在运行几次后退出单元格的循环执行。

这也有点问题,似乎不存在重新运行 现有单元格 的功能,或者初始化 run cells above 功能的单元格。但是我们将使用与之前相同的 github 帖子中的另一个建议来处理这个问题:

执行以下操作有助于我执行代码单元正下方的单元格。您还可以更改值以获取笔记本其他部分中的单元格。 display(Javascript('IPython.notebook.execute_cell_range(IPython.notebook.get_selected_index()+1, IPython.notebook.get_selected_index()+2)'))

带有建议工作流程的笔记本:

在下面的四个单元格中插入以下四个片段。单击菜单选项 Cell > Run all 一次,我们就可以开始了!

片段 1 - 导入和设置

import sys
import os
from IPython.core.display import display, HTML
from IPython.display import Javascript
from random import randint

# Trigger to randomly raise en error in the next cell
ErrorTrigger = randint(0, 9)

# Assignment of variables at first run of the Norebook
try: x1
except NameError: x1 = None
if x1 is None:
    %qtconsole # opens a qtconsole (for variable inspection and debugging)
    x1 = 0 # counter for NameError
    x2 = 0 # counter for assignment error (used in cells below)
    mr = 0 # counter for manual relaunch by button

    ErrorTriggers=[] # container for ErroTriggers
    print('NameErrors = ', x1)
else:
    x1 = x1 + 1
    ErrorTriggers.append(ErrorTrigger)
#print('Executions:', x1, '||', 'Triggers:', ErrorTriggers)

片段 2 - 错误的代理

# PROXY ERROR => INSERT YOUR CODE FROM HERE ################################################################
list1 = [1,2,3,4]

# 80 % chance of raising an error trying to delete an element that does not exist in the list
if ErrorTrigger > 2:
    elemDelete = 8 # error
else:
    elemDelete = 0 # not error
try:
    del list1[elemDelete]
    print('Executions:', x1, '||', 'Triggers:', ErrorTriggers)
    print('Routine success on attempt', x2 + 1)
    print('Error mesg: None')
    ErrorTriggers=[]
    x2 = 0 # reset error counter

# TO HERE #################################################################################################
except Exception:

    x2 = x2 + 1
    # Will end error handler after 5 attempts
    if x2 < 3:
        # As long as we're UNDER the attempt limit, the next cell executed by:
        display(Javascript('IPython.notebook.execute_cell_range(IPython.notebook.get_selected_index()+1,'+
                           ' IPython.notebook.get_selected_index()+2)'))
    else:
        # If we're OVER the attempt limit, it all ends here. The next cell is NOT run.
        # And NEITHER is the last cell with the button to relaunch the whole thing.

        print('Executions:', x1, '||', 'Triggers:', ErrorTriggers)
        print('Routine aborted after attempt', x2)
        print('Error msg:', sys.exc_info()[1]) # Returns a message describing the error
        # reset variables
        ErrorTriggers = []
        x2 = 0

片段 3 - 将上面的所有单元格重新运行为错误处理程序的单元格

display(Javascript('IPython.notebook.execute_cells_above()'))

片段 4 - 以 20% 的错误概率重新运行整个过程的单元格

HTML('''<script> </script> <form action="javascript:IPython.notebook.execute_cells_above()"><input type="submit" id="toggleButton" value="Run again!"></form>''')

几次测试运行后的屏幕截图:

在此处输入图像描述

如果片段中的评论不清楚,我很乐意添加更多详细信息。但是,如果您通过单击 Run Again! 运行笔记本几次,同时查看单元格 3 的输出,您将很快掌握整个内容是如何组合在一起的:

在此处输入图像描述

原文由 vestland 发布,翻译遵循 CC BY-SA 4.0 许可协议

我正在运行笔记本服务器 5.4.0,我有一个选项 Cell > Run All Above 似乎就是这样做的。

在此处输入图像描述

原文由 Nic Cottrell 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题