Skip to content

After IPYWidget Event Fires print no longer writes to sys.stdout #7613

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

Closed
pcasillo opened this issue Mar 17, 2025 · 7 comments
Closed

After IPYWidget Event Fires print no longer writes to sys.stdout #7613

pcasillo opened this issue Mar 17, 2025 · 7 comments
Labels
bug status:Needs Info status:Needs Triage Applied to issues that need triage

Comments

@pcasillo
Copy link

pcasillo commented Mar 17, 2025

I have checked the documentation and found no recent issues highlighting the same problem. I have seen the same issue as recently as 2021.
Recently, I upgraded my Jupyter extension in VSCode to 2025.2.0. Afterward, I can no longer write to STDOUT once I have created an IPYWidgets Output Widget (While using an On-Click Event). I have confirmed that rolling my extension back to 2024.11.0 eliminates the issue.

Please forgive me if I am missing something obvious.

I really appreciate any help you can provide.

Thanks,

anyio 4.9.0
argon2-cffi 23.1.0
argon2-cffi-bindings 21.2.0
arrow 1.3.0
asttokens 3.0.0
async-lru 2.0.5
attrs 25.3.0
babel 2.17.0
beautifulsoup4 4.13.3
bleach 6.2.0
certifi 2025.1.31
cffi 1.17.1
charset-normalizer 3.4.1
colorama 0.4.6
comm 0.2.2
debugpy 1.8.13
decorator 5.2.1
defusedxml 0.7.1
exceptiongroup 1.2.2
executing 2.2.0
fastjsonschema 2.21.1
fqdn 1.5.1
h11 0.14.0
httpcore 1.0.7
httpx 0.28.1
idna 3.10
ipykernel 6.29.5
ipython 8.34.0
ipywidgets 8.1.5
isoduration 20.11.0
jedi 0.19.2
Jinja2 3.1.6
json5 0.10.0
jsonpointer 3.0.0
jsonschema 4.23.0
jsonschema-specifications 2024.10.1
jupyter 1.1.1
jupyter_client 8.6.3
jupyter-console 6.6.3
jupyter_core 5.7.2
jupyter-events 0.12.0
jupyter-lsp 2.2.5
jupyter_server 2.15.0
jupyter_server_terminals 0.5.3
jupyterlab 4.3.6
jupyterlab_pygments 0.3.0
jupyterlab_server 2.27.3
jupyterlab_widgets 3.0.13
MarkupSafe 3.0.2
matplotlib-inline 0.1.7
mistune 3.1.2
nbclient 0.10.2
nbconvert 7.16.6
nbformat 5.10.4
nest-asyncio 1.6.0
notebook 7.3.3
notebook_shim 0.2.4
overrides 7.7.0
packaging 24.2
pandocfilters 1.5.1
parso 0.8.4
pip 23.0.1
platformdirs 4.3.6
prometheus_client 0.21.1
prompt_toolkit 3.0.50
psutil 7.0.0
pure_eval 0.2.3
pycparser 2.22
Pygments 2.19.1
python-dateutil 2.9.0.post0
python-json-logger 3.3.0
pywin32 310
pywinpty 2.0.15
PyYAML 6.0.2
pyzmq 26.3.0
referencing 0.36.2
requests 2.32.3
rfc3339-validator 0.1.4
rfc3986-validator 0.1.1
rpds-py 0.23.1
Send2Trash 1.8.3
setuptools 65.5.0
six 1.17.0
sniffio 1.3.1
soupsieve 2.6
stack-data 0.6.3
terminado 0.18.1
tinycss2 1.4.0
tomli 2.2.1
tornado 6.4.2
traitlets 5.14.3
types-python-dateutil 2.9.0.20241206
typing_extensions 4.12.2
uri-template 1.3.0
urllib3 2.3.0
wcwidth 0.2.13
webcolors 24.11.1
webencodings 0.5.1
websocket-client 1.8.0
widgetsnbextension 4.0.13

I created a Widget with a Single Button in a simple reproducer. On Click, I am writing to the Cell STDOUT and the Output widget. In version 2025.2.0 only the values written to the Widget are displayed, and all values to STDOUT are captured in the Jupyter Output as the following:

[trace] Unhandled widget kernel message: stream [object Object]
Unhandled kernel message from a widget: stream : {"name":"stdout","text":"Outside Widget\n"}

import ipywidgets as widgets 
from IPython.display import display, clear_output

print("Before Widget")

out = widgets.Output(layout={'border': '1px solid black'})

def button_on_click(b):
        
    out.clear_output()
    with out:
         print("Inside Widget")
    
    print('Outside Widget')
    
btn = widgets.Button(description="Test")
btn.on_click(button_on_click)

Container = widgets.VBox(children=[btn])

display(Container,out)
print('After Display')
@pcasillo pcasillo added bug status:Needs Triage Applied to issues that need triage labels Mar 17, 2025
@minrk
Copy link
Member

minrk commented Mar 18, 2025

Outputs are associated with the request that created them. For normal executions like running code in a cell, this is an execute_request. For button click events, this is a comm_msg triggered when the widget button is clicked. So since the print output is not associated with a cell execution, there isn't an output area to attach it to and it ends up discarded. That's why the with out: works: it explicitly routes messages to an OutputArea.

It may be that the vs code extension changed how they handle 'unrouted' output (output not associated with an output area). Some frontends choose to display these in some 'default' area, some choose to discard them. Both are valid choices. The vs code extension is not part of Jupyter, so you should problem bring this up over there.

@pcasillo
Copy link
Author

Hi @minrk

Thank you very much for your insight. Similarly, I see the same issue(s) in Jupyter Labs and Notebooks. I could only back out the extension in VS Code to validate when the change occurred. These notebooks have been in production for more than four years, and only recently has this output change started to happen. Is there a way to force back to STDOUT? I hoped setting the print "file" argument to sys.stdout would move it back to the cell.

Thanks,
Paul

@minrk
Copy link
Member

minrk commented Mar 18, 2025

Does the vs code package install a full pinned environment, including the kernel? If so, can you show both environments for the diff? I'm not sure what package change would have done this. It could be something in ipykernel affecting the parent-request association with widget messages.

I hoped setting the print "file" argument to sys.stdout would move it back to the cell.

It is going to 'stdout', but setting file doesn't specify what it's stdout of. What it isn't is stdout of a cell execution, so there is no unambiguously appropriate cell output area to send it to. I'm not sure if there's an option in a frontend to send output that's not produced by a cell to a cell's output .

Routing of output messages not produced by cell execution has been handled inconsistently over the years by various frontends, depending on exactly how various components interact.

If you want to force it back to some cell's output (which one?), you might be able to hook something up with an output widget.

For example, you can register a specific Output widget to capture all output produced during comm messages not explicitly captured otherwise:

# create an output area to display detached widget output
comm_out = widgets.Output()
display(comm_out)

# send detatched output created during comm msgs to our output area
ip = get_ipython()
original_comm_msg_handler = ip.kernel.shell_handlers["comm_msg"]


def captured_comm_msg(*args, **kwargs):
    with comm_out:
        return original_comm_msg_handler(*args, **kwargs)


ip.kernel.shell_handlers["comm_msg"] = captured_comm_msg

@danyeaw
Copy link

danyeaw commented Apr 1, 2025

Similarly, I see the same issue(s) in Jupyter Labs and Notebooks.

Hi @pcasillo, thanks for the issue report. Since this is the Notebook issue tracker, could you please provide a minimal reproducible example in Notebook where you see this issue? Thanks!

@danyeaw
Copy link

danyeaw commented Apr 15, 2025

Since we haven't received a response on this issue I'm going to close this one. If you can provide a reproducible example for JupyterLab or Notebook, please open a new issue. Thanks!

@danyeaw danyeaw closed this as not planned Won't fix, can't repro, duplicate, stale Apr 15, 2025
@pcasillo
Copy link
Author

The reproducer is directly above.

@pcasillo
Copy link
Author

import ipywidgets as widgets
from IPython.display import display, clear_output

print("Before Widget")

out = widgets.Output(layout={'border': '1px solid black'})

def button_on_click(b):

out.clear_output()
with out:
     print("Inside Widget")

print('Outside Widget')

btn = widgets.Button(description="Test")
btn.on_click(button_on_click)

Container = widgets.VBox(children=[btn])

display(Container,out)
print('After Display')

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug status:Needs Info status:Needs Triage Applied to issues that need triage
Projects
None yet
Development

No branches or pull requests

4 participants