Textualize / textual

The lean application framework for Python. Build sophisticated user interfaces with a simple Python API. Run your apps in the terminal and a web browser.
https://textual.textualize.io/
MIT License
25.37k stars 777 forks source link

Gracefully handle termination signals #5140

Open davidfokkema opened 1 day ago

davidfokkema commented 1 day ago

On macOS, and presumably similarly on *nix, you can do this:

import pathlib
import signal
import time

from textual.app import App, ComposeResult
from textual.widgets import Placeholder

class MinimalApp(App[None]):
    _signal = None

    def on_mount(self) -> None:
        signal.signal(signalnum=signal.SIGHUP, handler=self.catch_signal)
        signal.signal(signalnum=signal.SIGTERM, handler=self.catch_signal)

    def compose(self) -> ComposeResult:
        yield Placeholder("This is a minimal app.")

    def catch_signal(self, signum, frame) -> None:
        self._signal = signum
        self.exit()

app = MinimalApp()
app.run()

pathlib.Path("signal.txt").write_text(
    f"{time.monotonic()}: Received signal: {app._signal}"
)
print("Done")
print(f"Received signal: {app._signal}")

This will gracefully shutdown the app when the app is killed (with SIGTERM) or when the terminal is closed (sending a SIGHUP to child processes). Currently, in the case of SIGTERM, Textual does shutdown, but not gracefully and stdin/stdout are messed up. Default signal handlers would improve that.

On Windows, it might be a bit more difficult (maybe this would work: https://stackoverflow.com/questions/69323194/how-do-i-handle-windows-terminal-closing-event-in-python) and even on Linux there are reports it might be not as straightforward as hoped. Still, might be worth it?

github-actions[bot] commented 1 day ago

We found the following entry in the FAQ which you may find helpful:

Feel free to close this issue if you found an answer in the FAQ. Otherwise, please give us a little time to review.

This is an automated reply, generated by FAQtory