Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Deadlock combining ipywidgets.interact and IPython.display.Audio #2029

Open
YannickJadoul opened this issue Aug 4, 2023 · 3 comments
Open

Comments

@YannickJadoul
Copy link

YannickJadoul commented Aug 4, 2023

jupyter nbconvert --execute minimal_reproducer.ipynb --to html sometimes unpredictably hangs when executing the notebook.

I've managed to reduce the reproducing notebook to just a single cell, which combines ipywidgets.interact with a function which returns an IPython.display.Audio object as result of the function:

import glob
from IPython.display import Audio
import ipywidgets

def do_something(value):
    return Audio(value)

ipywidgets.interact(do_something, value=ipywidgets.Dropdown(options=sorted(glob.glob("audio/*.wav"))))

Some extra details:

  • Running this with --debug, I get the following output:
$jupyter nbconvert --debug --execute minimal_reproducer.ipynb --to html
[NbConvertApp] Searching ['/home/yannick/.jupyter', '/home/yannick/.local/etc/jupyter', '/usr/etc/jupyter', '/usr/local/etc/jupyter', '/etc/jupyter'] for config files
[NbConvertApp] Looking for jupyter_config in /etc/jupyter
[NbConvertApp] Looking for jupyter_config in /usr/local/etc/jupyter
[NbConvertApp] Looking for jupyter_config in /usr/etc/jupyter
[NbConvertApp] Looking for jupyter_config in /home/yannick/.local/etc/jupyter
[NbConvertApp] Looking for jupyter_config in /home/yannick/.jupyter
[NbConvertApp] Looking for jupyter_nbconvert_config in /etc/jupyter
[NbConvertApp] Looking for jupyter_nbconvert_config in /usr/local/etc/jupyter
[NbConvertApp] Looking for jupyter_nbconvert_config in /usr/etc/jupyter
[NbConvertApp] Looking for jupyter_nbconvert_config in /home/yannick/.local/etc/jupyter
[NbConvertApp] Looking for jupyter_nbconvert_config in /home/yannick/.jupyter
[NbConvertApp] Converting notebook minimal_reproducer.ipynb to html
[NbConvertApp] Notebook name is 'minimal_reproducer'
[NbConvertApp] Template paths:
	/home/yannick/.local/share/jupyter/nbconvert/templates/lab
	/home/yannick/.local/share/jupyter/nbconvert/templates/base
	/home/yannick/.local/share/jupyter
	/home/yannick/.local/share/jupyter/nbconvert/templates
	/home/yannick/.local/share/jupyter/nbconvert/templates/compatibility
	/usr/local/share/jupyter
	/usr/local/share/jupyter/nbconvert/templates
	/usr/local/share/jupyter/nbconvert/templates/compatibility
	/usr/share/jupyter
	/usr/share/jupyter/nbconvert/templates
	/usr/share/jupyter/nbconvert/templates/compatibility
	/home/yannick/.local/share/jupyter/nbconvert/templates
[NbConvertApp] Applying preprocessor: TagRemovePreprocessor
[NbConvertApp] Applying preprocessor: RegexRemovePreprocessor
[NbConvertApp] Applying preprocessor: ExecutePreprocessor
[NbConvertApp] Instantiating kernel 'Python 3 (ipykernel)' with kernel provisioner: local-provisioner
[NbConvertApp] Starting kernel: ['/usr/bin/python3', '-m', 'ipykernel_launcher', '-f', '/tmp/tmp2cfc0f6d.json', '--HistoryManager.hist_file=:memory:']
[NbConvertApp] Connecting to: tcp://127.0.0.1:49369
[NbConvertApp] connecting iopub channel to tcp://127.0.0.1:51491
[NbConvertApp] Connecting to: tcp://127.0.0.1:51491
[NbConvertApp] connecting shell channel to tcp://127.0.0.1:41635
[NbConvertApp] Connecting to: tcp://127.0.0.1:41635
[NbConvertApp] connecting stdin channel to tcp://127.0.0.1:51223
[NbConvertApp] Connecting to: tcp://127.0.0.1:51223
[NbConvertApp] connecting heartbeat channel to tcp://127.0.0.1:34265
[NbConvertApp] connecting control channel to tcp://127.0.0.1:49369
[NbConvertApp] Connecting to: tcp://127.0.0.1:49369
[NbConvertApp] Executing cell:
import glob
from IPython.display import Audio
import ipywidgets

def do_something(value):
    return Audio(value)

ipywidgets.interact(do_something, value=ipywidgets.Dropdown(options=sorted(glob.glob("audio/*.wav"))))
[NbConvertApp] msg_type: status
[NbConvertApp] content: {'execution_state': 'busy'}
[NbConvertApp] msg_type: execute_input
[NbConvertApp] content: {'code': 'import glob\nfrom IPython.display import Audio\nimport ipywidgets\n\ndef do_something(value):\n    return Audio(value)\n\nipywidgets.interact(do_something, value=ipywidgets.Dropdown(options=sorted(glob.glob("audio/*.wav"))))', 'execution_count': 1}
[NbConvertApp] msg_type: comm_open
[NbConvertApp] content: {'data': {'state': {'_model_module': '@jupyter-widgets/base', '_model_module_version': '2.0.0', '_model_name': 'LayoutModel', '_view_count': None, '_view_module': '@jupyter-widgets/base', '_view_module_version': '2.0.0', '_view_name': 'LayoutView', 'align_content': None, 'align_items': None, 'align_self': None, 'border_bottom': None, 'border_left': None, 'border_right': None, 'border_top': None, 'bottom': None, 'display': None, 'flex': None, 'flex_flow': None, 'grid_area': None, 'grid_auto_columns': None, 'grid_auto_flow': None, 'grid_auto_rows': None, 'grid_column': None, 'grid_gap': None, 'grid_row': None, 'grid_template_areas': None, 'grid_template_columns': None, 'grid_template_rows': None, 'height': None, 'justify_content': None, 'justify_items': None, 'left': None, 'margin': None, 'max_height': None, 'max_width': None, 'min_height': None, 'min_width': None, 'object_fit': None, 'object_position': None, 'order': None, 'overflow': None, 'padding': None, 'right': None, 'top': None, 'visibility': None, 'width': None}, 'buffer_paths': []}, 'comm_id': 'd00e3f900d174410b119e9a62bf1f3d3', 'target_name': 'jupyter.widget', 'target_module': None}
[NbConvertApp] msg_type: comm_open
[NbConvertApp] content: {'data': {'state': {'_model_module': '@jupyter-widgets/controls', '_model_module_version': '2.0.0', '_model_name': 'DescriptionStyleModel', '_view_count': None, '_view_module': '@jupyter-widgets/base', '_view_module_version': '2.0.0', '_view_name': 'StyleView', 'description_width': ''}, 'buffer_paths': []}, 'comm_id': '1058e0c87a294d56af529cf2ca1b0ab2', 'target_name': 'jupyter.widget', 'target_module': None}
[NbConvertApp] msg_type: comm_open
[NbConvertApp] content: {'data': {'state': {'_dom_classes': [], '_model_module': '@jupyter-widgets/controls', '_model_module_version': '2.0.0', '_model_name': 'DropdownModel', '_options_labels': ['audio/1_b.wav', 'audio/1_y.wav', 'audio/2_b.wav', 'audio/2_y.wav', 'audio/3_b.wav', 'audio/3_y.wav', 'audio/4_b.wav', 'audio/4_y.wav', 'audio/5_b.wav', 'audio/5_y.wav', 'audio/bat.wav', 'audio/bet.wav', 'audio/the_north_wind_and_the_sun.wav'], '_view_count': None, '_view_module': '@jupyter-widgets/controls', '_view_module_version': '2.0.0', '_view_name': 'DropdownView', 'description': '', 'description_allow_html': False, 'disabled': False, 'index': 0, 'layout': 'IPY_MODEL_d00e3f900d174410b119e9a62bf1f3d3', 'style': 'IPY_MODEL_1058e0c87a294d56af529cf2ca1b0ab2', 'tabbable': None, 'tooltip': None}, 'buffer_paths': []}, 'comm_id': '1bb52825004a414aafc3100657a46e80', 'target_name': 'jupyter.widget', 'target_module': None}
[NbConvertApp] msg_type: comm_open
[NbConvertApp] content: {'data': {'state': {'_model_module': '@jupyter-widgets/base', '_model_module_version': '2.0.0', '_model_name': 'LayoutModel', '_view_count': None, '_view_module': '@jupyter-widgets/base', '_view_module_version': '2.0.0', '_view_name': 'LayoutView', 'align_content': None, 'align_items': None, 'align_self': None, 'border_bottom': None, 'border_left': None, 'border_right': None, 'border_top': None, 'bottom': None, 'display': None, 'flex': None, 'flex_flow': None, 'grid_area': None, 'grid_auto_columns': None, 'grid_auto_flow': None, 'grid_auto_rows': None, 'grid_column': None, 'grid_gap': None, 'grid_row': None, 'grid_template_areas': None, 'grid_template_columns': None, 'grid_template_rows': None, 'height': None, 'justify_content': None, 'justify_items': None, 'left': None, 'margin': None, 'max_height': None, 'max_width': None, 'min_height': None, 'min_width': None, 'object_fit': None, 'object_position': None, 'order': None, 'overflow': None, 'padding': None, 'right': None, 'top': None, 'visibility': None, 'width': None}, 'buffer_paths': []}, 'comm_id': '680f378b839a466f97ed0988e6037d26', 'target_name': 'jupyter.widget', 'target_module': None}
[NbConvertApp] msg_type: comm_open
[NbConvertApp] content: {'data': {'state': {'_dom_classes': ['widget-interact'], '_model_module': '@jupyter-widgets/controls', '_model_module_version': '2.0.0', '_model_name': 'VBoxModel', '_view_count': None, '_view_module': '@jupyter-widgets/controls', '_view_module_version': '2.0.0', '_view_name': 'VBoxView', 'box_style': '', 'children': [], 'layout': 'IPY_MODEL_680f378b839a466f97ed0988e6037d26', 'tabbable': None, 'tooltip': None}, 'buffer_paths': []}, 'comm_id': 'c01bc0355e13449a8550dc6979da258d', 'target_name': 'jupyter.widget', 'target_module': None}
[NbConvertApp] msg_type: comm_msg
[NbConvertApp] content: {'data': {'method': 'update', 'state': {'description': 'value'}, 'buffer_paths': []}, 'comm_id': '1bb52825004a414aafc3100657a46e80'}
[NbConvertApp] msg_type: comm_open
[NbConvertApp] content: {'data': {'state': {'_model_module': '@jupyter-widgets/base', '_model_module_version': '2.0.0', '_model_name': 'LayoutModel', '_view_count': None, '_view_module': '@jupyter-widgets/base', '_view_module_version': '2.0.0', '_view_name': 'LayoutView', 'align_content': None, 'align_items': None, 'align_self': None, 'border_bottom': None, 'border_left': None, 'border_right': None, 'border_top': None, 'bottom': None, 'display': None, 'flex': None, 'flex_flow': None, 'grid_area': None, 'grid_auto_columns': None, 'grid_auto_flow': None, 'grid_auto_rows': None, 'grid_column': None, 'grid_gap': None, 'grid_row': None, 'grid_template_areas': None, 'grid_template_columns': None, 'grid_template_rows': None, 'height': None, 'justify_content': None, 'justify_items': None, 'left': None, 'margin': None, 'max_height': None, 'max_width': None, 'min_height': None, 'min_width': None, 'object_fit': None, 'object_position': None, 'order': None, 'overflow': None, 'padding': None, 'right': None, 'top': None, 'visibility': None, 'width': None}, 'buffer_paths': []}, 'comm_id': 'e7f16b501e99438e9281b32bd3fd307a', 'target_name': 'jupyter.widget', 'target_module': None}
[NbConvertApp] msg_type: comm_open
[NbConvertApp] content: {'data': {'state': {'_dom_classes': [], '_model_module': '@jupyter-widgets/output', '_model_module_version': '1.0.0', '_model_name': 'OutputModel', '_view_count': None, '_view_module': '@jupyter-widgets/output', '_view_module_version': '1.0.0', '_view_name': 'OutputView', 'layout': 'IPY_MODEL_e7f16b501e99438e9281b32bd3fd307a', 'msg_id': '', 'outputs': [], 'tabbable': None, 'tooltip': None}, 'buffer_paths': []}, 'comm_id': '34df9a2e8fe5474cb1bf5256f2524a37', 'target_name': 'jupyter.widget', 'target_module': None}
[NbConvertApp] msg_type: comm_msg
[NbConvertApp] content: {'data': {'method': 'update', 'state': {'children': ['IPY_MODEL_1bb52825004a414aafc3100657a46e80', 'IPY_MODEL_34df9a2e8fe5474cb1bf5256f2524a37']}, 'buffer_paths': []}, 'comm_id': 'c01bc0355e13449a8550dc6979da258d'}
[NbConvertApp] msg_type: comm_msg
[NbConvertApp] content: {'data': {'method': 'update', 'state': {'msg_id': '1a83a999-dfbe126f90f6b626080d6ee7_108239_3'}, 'buffer_paths': []}, 'comm_id': '34df9a2e8fe5474cb1bf5256f2524a37'}
[NbConvertApp] msg_type: clear_output
[NbConvertApp] content: {'wait': True}
[NbConvertApp] msg_type: display_data
[NbConvertApp] content: {'data': {'text/plain': '<IPython.lib.display.Audio object>', 'text/html': '\n                <audio  controls="controls" >\n                    <source src="data:audio/x-wav;base64,..." type="audio/x-wav" />\n                    Your browser does not support the audio element.\n                </audio>\n              '}, 'metadata': {}, 'transient': {}}
[NbConvertApp] msg_type: comm_msg
[NbConvertApp] content: {'data': {'method': 'update', 'state': {'msg_id': ''}, 'buffer_paths': []}, 'comm_id': '34df9a2e8fe5474cb1bf5256f2524a37'}
[NbConvertApp] msg_type: display_data
[NbConvertApp] content: {'data': {'text/plain': "interactive(children=(Dropdown(description='value', options=('audio/1_b.wav', 'audio/1_y.wav', 'audio/2_b.wav'…", 'application/vnd.jupyter.widget-view+json': {'version_major': 2, 'version_minor': 0, 'model_id': 'c01bc0355e13449a8550dc6979da258d'}}, 'metadata': {}, 'transient': {}}
[NbConvertApp] msg_type: execute_result
[NbConvertApp] content: {'data': {'text/plain': '<function __main__.do_something(value)>'}, 'metadata': {}, 'execution_count': 1}
[NbConvertApp] msg_type: status
[NbConvertApp] content: {'execution_state': 'idle'}
  • Sometimes, when the execution does halt and finish successfully, an error [IPKernelApp] ERROR | KeyboardInterrupt caught in kernel. shows up in the debug output, right after the previous lines.

  • Adding time.sleep(1) the pywidgets.interact line seems to provide a workaround, as far as I can test. So is there some sort of race condition going on?

@TermeHansen
Copy link

I often get similiar problems with plotly with nbconvert ending with the same
content: {'execution_state': 'idle'}
when using the --debug flag

and for me as well putting in some time.sleep(1) around seems to solve the issue. Clearly some race conditions taking place...

@YannickJadoul
Copy link
Author

@TermeHansen I agree about the smell of race conditions, but I didn't manage to figure out a consistent solution of where to put sleep.

@hjliu0206
Copy link

hjliu0206 commented May 11, 2024

i have raise an merge request about the issue
jupyter/nbclient#312

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants