python - 从 ipywidget 取消 Jupyter 执行
问题描述
我想创建一个按钮 ipywidget,允许在点击 Jupyter 中的取消按钮时停止执行。我见过几个例子(包括这个),但它们都需要能够修改进程本身正在运行的函数。
这听起来很简单,但我开始认为这是不可能的。然而,我对多进程缺乏了解可能正是我沮丧的原因。我尝试过的版本都没有工作。没有人真正运行我的功能(或者他们可能在后台运行)并且似乎没有人成功取消执行。
到目前为止,我已经尝试过:
选项1
import ipywidgets as widgets
from IPython.display import display
from functools import wraps
from time import sleep
from multiprocessing import Process as Thread
def stoppable_fun(stopper):
def decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
threaded_fun = Thread(target=func, args=args, kwargs=kwargs)
threaded_fun.start()
while threaded_fun.is_alive():
print("alive")
if not stopper.is_alive():
print("stopped", stopper.is_alive())
threaded_fun.terminate()
sleep(0.05)
return wrapper
return decorator
cancel_button_ly = widgets.Layout(width="auto", visibility="hidden")
cancel_button = widgets.Button(description="Cancel", layout=cancel_button_ly)
cancel_flag = False
def cancel_button_event_handler(obj):
print("Cancel")
cancel_flag = True
cancel_button.on_click(cancel_button_event_handler)
def check_cancel(timeout):
print("check def")
i = 0
while not cancel_flag and i < timeout:
print("checking")
sleep(0.1)
i += 0.1
print("check", cancel_flag)
class CancelableButton(widgets.HBox):
def __init__(self, *args, **kwargs):
self.button = widgets.Button(*args, **kwargs)
widgets.HBox.__init__(self, children=[self.button, cancel_button])
def on_click(self, func, *args, **kwargs):
def new_function(*args, **kwargs):
self.button.disabled = True
cancel_button_ly.visibility = "visible"
sleep(0.5)
thread_check_cancel = Thread(target=check_cancel, args=(10,))
stoppable = stoppable_fun(thread_check_cancel)(func)
try:
thread_check_cancel.start()
stoppable()
print("is check alive?", thread_check_cancel.is_alive())
except KeyboardInterrupt:
print("Canceled!")
finally:
thread_check_cancel.terminate()
cancel_button_ly.visibility = "hidden"
self.button.disabled = False
cancel_flag = False
self.button.on_click(new_function, *args, **kwargs)
选项 2
import ipywidgets as widgets
from IPython.display import display
from time import sleep
import multiprocessing
cancel_event = multiprocessing.Event()
def cancel_button_event_handler(obj):
print("Cancelled")
cancel_event.set()
cancel_button = widgets.Button(description="Cancel")
cancel_button.on_click(cancel_button_event_handler)
def func(obj):
for i in range(10):
print("Runing calculation", i)
sleep(0.5)
threaded_func = multiprocessing.Process(target=func)
def new_function(obj):
threaded_func = multiprocessing.Process(target=func)
threaded_func.start()
while threaded_func.is_alive():
print("alive")
sleep(0.1)
if cancel_event.is_set():
print("cancelled")
threaded_func.terminate()
cancel_event.clear()
button = widgets.Button(description="Calculate")
button.on_click(new_function)
display(button)
display(cancel_button)
选项 3
import ipywidgets as widgets
from IPython.display import display
from functools import wraps
from time import sleep
import multiprocessing
class CancelableButton(widgets.HBox):
def __init__(self, func):
self.cancel_button = widgets.Button(description="Cancel")
self.button = widgets.Button(description="Calculate")
widgets.HBox.__init__(self, children=[self.button, self.cancel_button])
def on_click(self, func):
def new_function(obj):
threaded_func = multiprocessing.Process(target=func)
def cancel_button_event_handler(obj):
print("Cancelled")
threaded_func.terminate()
self.cancel_button.on_click(cancel_button_event_handler)
self.button.disabled = True
try:
print("Start")
threaded_func.start()
print("Calculating", threaded_func.is_alive())
threaded_func.join()
print("Done", threaded_func.exitcode)
finally:
self.button.disabled = False
self.button.on_click(new_function)
btn_ly = widgets.Layout(width="auto")
def func(obj):
for i in range(10):
print("Runing calculation", i)
sleep(0.5)
btn = CancelableButton(func)
btn_o = widgets.Output()
display(btn, btn_o)
btn.on_click(func)
任何帮助澄清我做错了什么,或者为什么不可能实现我正在尝试的事情,我们将不胜感激。
解决方案
推荐阅读
- java - 单击时导航不会进入下一个片段
- amazon-web-services - 使用 scp 在 EC2 实例之间传输文件会导致“错误的所有者或权限”
- java - 如何在android java中做音频循环15次
- spring-boot - How to set profile for Spring Application to be used in Minikube
- angular9 - Angular Ivy 编译器、ngtsc、ngcc、ngc、aot、jit、tsc
- python - Microsoft Graph 访问 onenote 作为守护程序服务返回无效范围
- c# - 拆分不显示所有字符串
- javascript - 嵌套对象的默认值
- kubernetes - 在 terraform 中授予事件查看权限
- visual-studio-code - 部署和检索命令时无法读取 Salesforce CLI 中未定义的属性“getInstance”