调用.close()方法后如何重新显示ipython widgets组件
问题成因
调用widget.close()方法后无法重新展示该组件的核心原因是:close()为实例销毁操作,而非临时隐藏:
- 执行
close()时会直接关闭Python内核与前端页面之间的组件通信通道 - 组件对应的前端模型、渲染视图都会被完全销毁,仅保留Python侧的无效空实例
- 后续再对该实例调用
display()时,内核无法和前端建立通信,自然不会渲染出任何组件
修复方案
这里提供两种可直接落地的修复方式:
方案1:用隐藏替换销毁(推荐)
将原有所有调用.close()的逻辑,替换为修改组件layout.display属性,组件实例不会被销毁,可随时切换显示状态:
import ipywidgets as widgets from IPython.display import display, clear_output orgs_list = ["org_1", "org_2"] selectOrg = widgets.Dropdown(options = orgs_list) selectDays = widgets.IntSlider(min = 7, max = 90, value = 30, step = 1) submitOrgButton = widgets.Button(description = 'Submit', button_style='info', tooltip = "Click here to submit") submitUserButton = widgets.Button(description = 'Submit', button_style='info', tooltip = "Click here to submit") submitDaysButton = widgets.Button(description='Submit', button_style='info', tooltip = "Click here to submit") clearOutputButton = widgets.Button(description='New Query', button_style='info', tooltip='Make another query') def submitOrgHandler(obj): print(f"Selected {selectOrg.label.upper()}") # 替换close为隐藏 selectOrg.layout.display = 'none' submitOrgButton.layout.display = 'none' org_id = selectOrg.value user_emails = ["user_email_1", "user_email_2"] user_ids = ["user_id_1", "user_id_2"] user_tuples = [(email, _id) for email, _id in zip(user_emails, user_ids)] global selectUser selectUser = widgets.Dropdown(options = user_tuples) print("Please select a user:") display(selectUser) display(submitUserButton) def submitUserHandler(obj): print(f"Selected {selectUser.label}") selectUser.layout.display = 'none' submitUserButton.layout.display = 'none' print("Please select a timespan:") display(selectDays) display(submitDaysButton) def submitMetricHandler(obj): print(f"Selected timespan: {selectDays.value} days \n") n_days = selectDays.value selectDays.layout.display = 'none' submitDaysButton.layout.display = 'none' print(f'Displaying information in the last {selectDays.value} days for {selectUser.label}...') user_email = selectUser.label # Do some plotting here print("{Plot goes here!}") display(clearOutputButton) def clearOutputHandler(obj): clear_output() # 重置组件显示状态 selectOrg.layout.display = 'block' submitOrgButton.layout.display = 'block' print("Please select an organisation, a user and a timespan:") display(selectOrg) display(submitOrgButton) print("Please select an organisation, a user and a timespan:") display(selectOrg) display(submitOrgButton) submitOrgButton.on_click(submitOrgHandler) submitUserButton.on_click(submitUserHandler) submitDaysButton.on_click(submitMetricHandler) clearOutputButton.on_click(clearOutputHandler)
方案2:重置时重新创建组件实例
如果需要销毁组件释放内存,就在重置逻辑里重新初始化所有被销毁的组件,不要复用旧实例:
仅需要修改全局变量初始化逻辑和clearOutputHandler即可:
# 全局仅保留不变的配置和静态组件 orgs_list = ["org_1", "org_2"] submitUserButton = widgets.Button(description = 'Submit', button_style='info', tooltip = "Click here to submit") submitDaysButton = widgets.Button(description='Submit', button_style='info', tooltip = "Click here to submit") clearOutputButton = widgets.Button(description='New Query', button_style='info', tooltip='Make another query') # 新增初始化方法,每次重置调用生成新实例 def init_base_widgets(): selectOrg = widgets.Dropdown(options = orgs_list) selectDays = widgets.IntSlider(min = 7, max = 90, value = 30, step = 1) submitOrgButton = widgets.Button(description = 'Submit', button_style='info', tooltip = "Click here to submit") submitOrgButton.on_click(submitOrgHandler) return selectOrg, selectDays, submitOrgButton # 首次初始化 selectOrg, selectDays, submitOrgButton = init_base_widgets() # 其他业务handler逻辑保持不变,仅修改clearOutputHandler def clearOutputHandler(obj): global selectOrg, selectDays, submitOrgButton clear_output() # 重新生成新实例,替换旧的已销毁实例 selectOrg, selectDays, submitOrgButton = init_base_widgets() print("Please select an organisation, a user and a timespan:") display(selectOrg) display(submitOrgButton)
内容的提问来源于stack exchange,提问作者GSwart
相关产品推荐
相关产品推荐

