Jupyter笔记本中阻止单元格执行的环境管理器
项目描述
ipython_blocking
ipython_blocking
是一个Jupyter笔记本中捕获单元格执行消息的环境管理器,同时提供了方便的魔法命令 %block
和 %blockrun
。阻止笔记本执行的主要用例是等待用户与 ipywidgets 交互,然后引用在那些小部件中输入的值。
安装
ipython_blocking
在 PyPI 上,使用pip进行安装。
pip install ipython_blocking
用法
尝试在Binder中运行演示笔记本,以查看 ipython_blocking
的实际应用。使用 %blockrun
魔法和运行笔记本的“单元格 -> 运行所有”是使用 ipython_blocking
最常见的方式。%blockrun button
停止从“单元格 -> 运行所有”开始的单元格执行消息,并将一个“单元格 -> 运行所有以下”处理程序附加到按钮上,这样在用户填写其他小部件值后,笔记本可以按顺序运行,而不需要回调函数。
### cell #1
import ipywidgets as widgets
import ipython_blocking # enables %block and %blockrun magic
text = widgets.Text()
dropdown = widgets.Dropdown(options=['', 'foo', 'bar', 'baz'])
button = widgets.Button(description='Run')
box = widgets.VBox(children=[text, dropdown, button])
box
### cell #2
%blockrun button
### cell #3 -- doesn't execute until the 'Run' button is pressed
### This gives the user a chance to interact with the Text and Dropdown widgets
print(text.value)
print(dropdown.value)
(此.gif中未出现下拉菜单,因为它在Windows屏幕捕获中被视为“单独的窗口”,对此表示歉意!)
CaptureExecution
ipython_blocking
通过创建一个改变 IPython.shell.kernel['execute_request']
处理程序行为的环境管理器来“阻止”单元格执行。当你在Jupyter笔记本中执行一个单元格时,它会向内核发送一个包含该代码的 execute_request
消息。
当 CaptureExecution
管理器“阻止”时,它会将这些消息存储在列表中,而不是实际执行它们。当环境管理器退出时,它会将处理程序重置为原始行为,然后重放存储的消息或丢弃它们。
import ipython_blocking
ctx = ipython_blocking.CaptureExecution(replay=True)
with ctx:
while True:
if break_function():
break
ctx.step() # handles all other messages that aren't 'execute_request' including widget value changes
%block
在导入 ipython_blocking
时,%block
魔法被启用。它接受一个函数或小部件对象,并创建一个 CaptureExecution
管理器,直到该函数返回 True 或小部件值发生变化时才阻止。
# cell 1
import ipywidgets as widgets
import ipython_blocking
dd = widgets.Dropdown(options=['', 'foo', 'bar', 'baz'])
dd
# cell 2
%block dd
# cell 3
# Won't actually be executed until the user chooses an option in the dd widget
print(dd.value)
%blockrun
%blockrun
魔法类似于 %block
,但它只接受 ipywidgets.Button
目标,并将其附加到按钮上的“单元 -> 运行以下所有内容”处理器。如果您预计 NoteBook 的应用程序逻辑将被多次运行(并且/或者不想重新初始化小部件,因为用户可能只更改了众多选项之一),那么 %blockrun
是更好的魔法。
当 NoteBook 首次渲染时,通常很方便使目标 Button
不可点击,然后在其他小部件上添加 .observe
处理器,这些小部件可以在某些输入验证发生时使 Button
可点击。
# cell 1
import ipywidgets as widgets
import ipython_blocking
text = widgets.Text()
dd = widgets.Dropdown(options=['', 'foo', 'bar', 'baz'])
button = widgets.Button(description='Run', disabled=True)
def validation(ev):
"make button clickable if user has put in more than 5 characters and chosen a dropdown option"
if len(text.value) > 5 and dd.value:
button.disabled = False
else:
button.disabled = True
text.observe(validation)
dd.observe(validation)
box = widgets.VBox(children=[text, dd, button])
box
# cell 2
%blockrun button
# cell 3
print(text.value)
print(dd.value)
替代方案
用户交互后获取小部件值的另一种方法是使用 事件回调 来结构 NoteBook,或将代码 异步 编写。
我相信以线性同步的方式编写 Jupyter Notebook 的应用程序逻辑,尽可能多地使用笔记本全局变量,具有重大优势。
- 更好的工作流程内省和理解(无需在代码中布满
global
和print
语句) - 当出现问题时,更容易进行调试
- 更容易将代码分解成小块/单元
项目详情
下载文件
下载适合您平台的应用程序。如果您不确定选择哪个,请了解更多关于 安装软件包 的信息。