prompt-toolkit / python-prompt-toolkit

Library for building powerful interactive command line applications in Python
https://python-prompt-toolkit.readthedocs.io/
BSD 3-Clause "New" or "Revised" License
9.11k stars 718 forks source link

Fullscreen application - stderr tears terminal output #1694

Closed trevorbayless closed 1 year ago

trevorbayless commented 1 year ago

Is there a common approach to handling stderr output while a fullscreen application is running? I've attached some test code which uses the webbrowser to open the default web browser on click, enter, or F1. The webbrowser module spits out a few errors to stderr which ends up tearing the fullscreen application.

I know on prompt applications, there's a patch_stderr method to tie things in nicely, but is there anything for fullscreen applications? Is the approach to redirect stderr elsewhere?

This same issue can be seen if you happen to not catch a raised exception.

Before browser open: image

After browser open: image

Note The above errors are not uncaught exceptions, but stderr output from the webbrowser module. There is currently not a way to suppress these messages.

Example code

#!/usr/bin/env python
import webbrowser
from prompt_toolkit.application import Application
from prompt_toolkit.key_binding import KeyBindings
from prompt_toolkit.layout import Layout, HSplit
from prompt_toolkit.widgets import Label, Button

def open_browser():
    webbrowser.open('http://google.com', new=2)

bindings = KeyBindings()
@bindings.add("f1")
def _(event):
    open_browser()

open_button = Button(text="Open browser", handler=open_browser)

root_container = HSplit(
    [
        Label("Press enter or F1 to open the browser"),
        open_button
    ]
)

application = Application(
    layout=Layout(root_container, focused_element=open_button),
    key_bindings=bindings,
    mouse_support=True,
    full_screen=True,
)

if __name__ == "__main__":
    application.run()
jonathanslenders commented 1 year ago

patch_stdout only patches sys.stdout/stderr within the Python process. It has no control over a subprocess like a web browser. (It has not much to do with the app running in full screen). I'm not sure how to do it for the webbrowser module, but it needs to spawn a subprocess for which the stdout/stderr are not attached to the current PTY, but instead maybe /dev/null.

trevorbayless commented 1 year ago

Thanks for the information. And in the case of a possible uncaught exception (which also tears the output) would the only possibility be redirecting stderr elsewhere (like a log file) right after starting the fullscreen application to avoid the tearing?