MainLoop and Event Loops

MainLoop

class urwid.MainLoop(widget: AbstractWidget, palette: Iterable[tuple[str, str] | tuple[str, str, str] | tuple[str, str, str, str] | tuple[str, str, str, str, str, str]] = (), screen: BaseScreen | None = None, handle_mouse: bool = True, input_filter: Callable[[list[str | tuple[str, int, int, int]], list[int]], list[str | tuple[str, int, int, int]]] | None = None, unhandled_input: Callable[[str | tuple[str, int, int, int]], bool | None] | None = None, event_loop: EventLoop | None = None, pop_ups: bool = False)

This is the standard main loop implementation for a single interactive session.

Parameters:
  • widget – the topmost widget used for painting the screen, stored as widget and may be modified. Must be a box widget.

  • palette – initial palette for screen

  • screen – screen to use, default is a new raw_display.Screen instance; stored as screen

  • handle_mouse – True to ask screen to process mouse events

  • input_filter – a function to filter input before sending it to widget, called from input_filter()

  • unhandled_input – a function called when input is not handled by widget, called from unhandled_input()

  • event_loop – if screen supports external an event loop it may be given here, default is a new SelectEventLoop instance; stored as event_loop

  • pop_ups – True to wrap widget with a PopUpTarget instance to allow any widget to open a pop-up anywhere on the screen

screen

The screen object this main loop uses for screen updates and reading input

event_loop

The event loop object this main loop uses for waiting on alarms and IO

Note

Some event_loop implementations accept an async def callback in addition to a plain callable - see the specific implementation’s own documentation for whether it does, and how it runs one. set_alarm_in(), set_alarm_at(), watch_file() and watch_pipe() all detect an async def callback and pass that detection through to event_loop; whether it actually does anything still depends on event_loop.

Set up the main loop around a top-level widget, a screen and an event loop.

Raises:

NotImplementedError – an event_loop is given but screen does not support external event loops.

draw_screen() → None

Render the widgets and paint the screen.

This method is called automatically from entering_idle(), which runs whenever the event loop is about to go idle – including after handling input and after an alarm callback fires. So screen updates made from input handlers or alarm callbacks are redrawn automatically.

If you modify the widgets displayed from somewhere else, such as another thread or a callback that does not go through the event loop’s idle handling, you will need to call this method yourself to repaint the screen.

entering_idle() → None

Call draw_screen() to update the screen when anything has changed.

This method is called whenever the event loop is about to enter the idle state.

input_filter(keys: list[str | tuple[str, int, int, int]], raw: list[int]) → list[str | tuple[str, int, int, int]]

Pass each of the input events and raw keystroke values through input_filter.

These values are passed to the input_filter function passed to the constructor. That function must return a list of keys to be passed to the widgets to handle. If no input_filter was defined this implementation will return all the input events.

property pop_ups: bool

Return whether pop-up widgets opened via PopUpLauncher are shown automatically.

process_input(keys: Iterable[str | tuple[str, int, int, int]]) → bool

Pass keyboard input and mouse events to widget.

This method is called automatically from the run() method when there is input, but may also be called to simulate input from the user.

keys is a list of input returned from screen’s get_input() or get_input_nonblocking() methods.

Returns True if any key was handled by a widget or the unhandled_input() method.

Raises:

TypeError – an item of keys is neither a key name nor a mouse event tuple.

remove_alarm(handle: Any) → bool

Remove an alarm. Return True if handle was found, False otherwise.

remove_watch_file(handle: Any) → bool

Remove a watch file. Returns True if the watch file exists, False otherwise.

remove_watch_pipe(write_fd: int) → bool

Close the read end of the pipe and remove the watch created by watch_pipe().

..note:: You are responsible for closing the write end of the pipe.

Returns True if the watch pipe exists, False otherwise

run() → None

Start the main loop handling input events and updating the screen.

The loop will continue until an ExitMainLoop exception is raised.

If you would prefer to manage the event loop yourself, don’t use this method. Instead, call start() before starting the event loop, and stop() once it’s finished.

set_alarm_at(tm: float, callback: Callable[[Self, _T | None], Any], user_data: _T | None = None) → Any

Schedule an alarm at tm time that will call callback from the within the run() function.

Returns a handle that may be passed to remove_alarm().

Parameters:
  • tm – time to call callback e.g. time.time() + 5

  • callback – function to call with two parameters: this main loop object and user_data

  • user_data – optional user data to pass to the callback

Note

callback may be an async def function on an event_loop implementation that supports one; see the note on MainLoop.

set_alarm_in(sec: float, callback: Callable[[Self, _T | None], Any], user_data: _T | None = None) → Any

Schedule an alarm in sec seconds that will call callback from the within the run() method.

Parameters:
  • sec – seconds until alarm

  • callback – function to call with two parameters: this main loop object and user_data

  • user_data – optional user data to pass to the callback

Note

callback may be an async def function on an event_loop implementation that supports one; see the note on MainLoop.

start() → StoppingContext

Set up the main loop, hooking into the event loop where necessary.

Starts the screen if it hasn’t already been started.

If you want to control starting and stopping the event loop yourself, you should call this method before starting, and call stop once the loop has finished. You may also use this method as a context manager, which will stop the loop automatically at the end of the block:

with main_loop.start():

…

Note that some event loop implementations don’t handle exceptions specially if you manage the event loop yourself. In particular, the Twisted and asyncio loops won’t stop automatically when ExitMainLoop (or anything else) is raised.

Raises:

CantUseExternalLoop – the screen does not support external event loops.

stop() → None

Clean up any hooks added to the event loop.

Only call this if you’re managing the event loop yourself, after the loop stops.

unhandled_input(data: str | tuple[str, int, int, int]) → bool | None

Call the unhandled_input function passed to the constructor with any input not handled by the widgets.

If no unhandled_input was defined then the input will be ignored.

input is the keyboard or mouse input.

The unhandled_input function should return True if it handled the input.

watch_file(fd: int, callback: Callable[[], Any]) → Any

Call callback when fd has some data to read. No parameters are passed to callback.

Returns a handle that may be passed to remove_watch_file().

Note

callback is passed to event_loop unwrapped, so it may be an async def function on an event_loop implementation that supports one; see the note on MainLoop.

watch_pipe(callback: Callable[[bytes], bool | None]) → int

Create a pipe used by another thread or subprocess to trigger callback in the main loop.

Parameters:

callback – function taking one parameter to call from within the process/thread running the main loop

This method returns a file descriptor attached to the write end of a pipe. The read end of the pipe is added to the list of files event_loop is watching. When data is written to the pipe the callback function will be called and passed a single value containing data read from the pipe.

This method may be used any time you want to update widgets from another thread or subprocess.

Data may be written to the returned file descriptor with os.write(fd, data). Ensure that data is less than 512 bytes (or 4K on Linux) so that the callback will be triggered just once with the complete value of data passed in.

If the callback returns False then the watch will be removed from event_loop and the read end of the pipe will be closed. You are responsible for closing the write end of the pipe with os.close(fd).

Note

callback may be an async def function on an event_loop implementation that supports one; see the note on MainLoop.

property widget: AbstractWidget

Property for the topmost widget used to draw the screen.

This must be a box widget.

SelectEventLoop

class urwid.SelectEventLoop

Event loop based on selectors.DefaultSelector.select().

Initialize with no alarms or watched files yet.

alarm(seconds: float, callback: Callable[[], Any]) → tuple[float, int, Callable[[], Any]]

Call callback() a given time from now.

No parameters are passed to callback. Returns a handle that may be passed to remove_alarm().

Parameters:
  • seconds – floating point time to wait before calling callback

  • callback – function to call from event loop

enter_idle(callback: Callable[[], Any]) → int

Add a callback for entering idle.

Returns a handle that may be passed to remove_idle()

remove_alarm(handle: tuple[float, int, Callable[[], Any]]) → bool

Remove an alarm.

Returns True if the alarm exists, False otherwise

remove_enter_idle(handle: int) → bool

Remove an idle callback.

Returns True if the handle was removed.

remove_watch_file(handle: int) → bool

Remove an input file.

Returns True if the input file exists, False otherwise

run() → None

Start the event loop.

Exit the loop when any callback raises an exception. If ExitMainLoop is raised, exit cleanly.

run_in_executor(executor: Executor, func: Callable[_Spec, _T], *args: _Spec.args, **kwargs: _Spec.kwargs) → Future[_T]

Run callable in executor.

Parameters:
  • executor – Executor to use for running the function

  • func – function to call

  • args – positional arguments to function

  • kwargs – keyword arguments to function

Returns:

future object for the function call outcome.

watch_file(fd: int, callback: Callable[[], Any]) → int

Call callback() when fd has some data to read.

No parameters are passed to callback. Returns a handle that may be passed to remove_watch_file().

Parameters:
  • fd – file descriptor to watch for input

  • callback – function to call when input is available

AsyncioEventLoop

class urwid.AsyncioEventLoop(*, loop: AbstractEventLoop | None = None, **kwargs: Any)

Event loop based on the standard library asyncio module.

Warning

Under Windows, AsyncioEventLoop globally enforces WindowsSelectorEventLoopPolicy as a side-effect of creating a class instance. Original event loop policy is restored in destructor method.

Note

If you make any changes to the urwid state outside of it handling input or responding to alarms (for example, from asyncio.Task running in background), and wish the screen to be redrawn, you must call MainLoop.draw_screen() method of the main loop manually.

A good way to do this:

asyncio.get_event_loop().call_soon(main_loop.draw_screen)

Note

alarm(), watch_file() and enter_idle() accept an async def callback in addition to a plain callable. A coroutine function is scheduled as an asyncio.Task instead of being called directly.

Wrap loop, or the current asyncio event loop when none is given.

alarm(seconds: float, callback: Callable[[], Any]) → asyncio.TimerHandle

Call callback() a given time from now.

No parameters are passed to callback. Returns a handle that may be passed to remove_alarm().

Parameters:
  • seconds – time in seconds to wait before calling callback

  • callback – function to call from event loop

enter_idle(callback: Callable[[], Any]) → int

Add a callback for entering idle.

Returns a handle that may be passed to remove_enter_idle()

remove_alarm(handle: TimerHandle) → bool

Remove an alarm.

Returns True if the alarm exists, False otherwise

remove_enter_idle(handle: int) → bool

Remove an idle callback.

Returns True if the handle was removed.

remove_watch_file(handle: int) → bool

Remove an input file.

Returns True if the input file exists, False otherwise

run() → None

Start the event loop.

Exit the loop when any callback raises an exception. If ExitMainLoop is raised, exit cleanly.

Raises:

BaseException – the exception that stopped the loop, once the loop has been left.

run_in_executor(executor: Executor | None, func: Callable[_Spec, _T], *args: _Spec.args, **kwargs: _Spec.kwargs) → asyncio.Future[_T]

Run callable in executor.

Parameters:
  • executor – Executor to use for running the function. Default asyncio executor is used if None.

  • func – function to call

  • args – arguments to function (positional only)

  • kwargs – keyword arguments to function (keyword only)

Returns:

future object for the function call outcome.

watch_file(fd: int, callback: Callable[[], Any]) → int

Call callback() when fd has some data to read.

No parameters are passed to callback. Returns a handle that may be passed to remove_watch_file().

Parameters:
  • fd – file descriptor to watch for input

  • callback – function to call when input is available

TrioEventLoop

class urwid.TrioEventLoop

Event loop based on the trio module.

trio is an async library for Python 3.5 and later.

Note

alarm(), watch_file() and enter_idle() accept an async def callback in addition to a plain callable. A coroutine function is scheduled as a task in the main loop’s nursery instead of being called directly.

Initialize the Trio event loop.

alarm(seconds: float, callback: Callable[[], Any]) → trio.CancelScope

Call callback() a given time from now.

Parameters:
  • seconds – time in seconds to wait before calling the callback

  • callback – function to call from the event loop

Returns:

a handle that may be passed to remove_alarm()

No parameters are passed to the callback.

enter_idle(callback: Callable[[], Any]) → int

Call callback() when the event loop enters the idle state.

There is no such thing as being idle in a Trio event loop so we simulate it by repeatedly calling callback() with a short delay.

remove_alarm(handle: CancelScope) → bool

Remove an alarm.

Parameters:

handle – the handle of the alarm to remove

remove_enter_idle(handle: int) → bool

Remove an idle callback.

Parameters:

handle – the handle of the idle callback to remove

remove_watch_file(handle: CancelScope) → bool

Remove a file descriptor being watched for input.

Parameters:

handle – the handle of the file descriptor callback to remove

Returns:

True if the file descriptor was watched, False otherwise

run() → None

Start the event loop.

Exit the loop when any callback raises an exception. If ExitMainLoop is raised, exit cleanly.

async run_async() → None

Start the main loop and block asynchronously until the main loop exits.

This allows one to embed an urwid app in a Trio app even if the Trio event loop is already running. Example:

with trio.open_nursery() as nursery:
    event_loop = urwid.TrioEventLoop()

    # [...launch other async tasks in the nursery...]

    loop = urwid.MainLoop(widget, event_loop=event_loop)
    with loop.start():
        await event_loop.run_async()

    nursery.cancel_scope.cancel()
watch_file(fd: int | SupportsFileno, callback: Callable[[], Any]) → trio.CancelScope

Call callback() when the given file descriptor has some data to read.

No parameters are passed to the callback.

Parameters:
  • fd – file descriptor to watch for input

  • callback – function to call when some input is available

Returns:

a handle that may be passed to remove_watch_file()

GLibEventLoop

class urwid.GLibEventLoop

Event loop based on GLib.MainLoop.

Deprecated since version 4.1.7: This API will be removed in version 6.0.

Initialize a fresh GLib.MainLoop with no alarms or watched files yet.

alarm(seconds: float, callback: Callable[[], Any]) → tuple[int, Callable[[], Any]]

Call callback() a given time from now.

No parameters are passed to callback. Returns a handle that may be passed to remove_alarm().

Parameters:
  • seconds – floating point time to wait before calling callback

  • callback – function to call from event loop

enter_idle(callback: Callable[[], Any]) → int

Add a callback for entering idle.

Returns a handle that may be passed to remove_enter_idle()

handle_exit(f: Callable[_Spec, _T]) → Callable[_Spec, _T | Literal[False]]

Wrap f so that ExitMainLoop raised inside it exits the GLibEventLoop cleanly.

Store the exception info if some other exception occurs, it will be reraised after the loop quits.

f – function to be wrapped

remove_alarm(handle: tuple[int, Callable[[], Any]]) → bool

Remove an alarm.

Returns True if the alarm exists, False otherwise

remove_enter_idle(handle: int) → bool

Remove an idle callback.

Returns True if the handle was removed.

remove_watch_file(handle: int) → bool

Remove an input file.

Returns True if the input file exists, False otherwise

run() → None

Start the event loop.

Exit the loop when any callback raises an exception. If ExitMainLoop is raised, exit cleanly.

Raises:

BaseException – the exception that stopped the loop, once the loop has been left.

run_in_executor(executor: Executor, func: Callable[_Spec, _T], *args: _Spec.args, **kwargs: _Spec.kwargs) → Future[_T]

Run callable in executor.

Parameters:
  • executor – Executor to use for running the function

  • func – function to call

  • args – positional arguments to function

  • kwargs – keyword arguments to function

Returns:

future object for the function call outcome.

set_signal_handler(signum: int, handler: Callable[[int, FrameType | None], Any] | int | signal.Handlers) → None

Set the signal handler for signal signum.

Warning

Because this method uses the GLib-specific unix_signal_add function, its behaviour is different than signal.signal().

If signum is not SIGHUP, SIGINT, SIGTERM, SIGUSR1, SIGUSR2 or SIGWINCH, this method performs no actions and immediately returns None.

Returns None in all cases (unlike signal.signal()).

Parameters:
  • signum – signal number

  • handler – function (taking signum as its single argument), or signal.SIG_IGN, or signal.SIG_DFL

watch_file(fd: int, callback: Callable[[], Any]) → int

Call callback() when fd has some data to read.

No parameters are passed to callback. Returns a handle that may be passed to remove_watch_file().

Parameters:
  • fd – file descriptor to watch for input

  • callback – function to call when input is available

TwistedEventLoop

class urwid.TwistedEventLoop(reactor: ReactorBase | None = None, manage_reactor: bool = True)

Event loop based on Twisted.

Initialize the event loop, wrapping reactor or Twisted’s default reactor.

Parameters:

reactor – reactor to use

Param:

manage_reactor: True if you want this event loop to run and stop the reactor.

Warning

Twisted’s reactor doesn’t like to be stopped and run again. If you need to stop and run your MainLoop, consider setting manage_reactor=False and take care of running/stopping the reactor at the beginning/ending of your program yourself.

You can also forego using MainLoop’s run() entirely, and instead call start() and stop() before and after starting the reactor.

alarm(seconds: float, callback: Callable[[], Any]) → DelayedCall

Call callback() a given time from now.

No parameters are passed to callback. Returns a handle that may be passed to remove_alarm().

Parameters:
  • seconds – floating point time to wait before calling callback

  • callback – function to call from event loop

enter_idle(callback: Callable[[], Any]) → int

Add a callback for entering idle.

Returns a handle that may be passed to remove_enter_idle()

handle_exit(f: Callable[_Spec, _T], enable_idle: bool = True) → Callable[_Spec, _T | None]

Wrap f so that ExitMainLoop raised inside it exits the TwistedEventLoop cleanly.

Store the exception info if some other exception occurs, it will be reraised after the loop quits.

f – function to be wrapped

remove_alarm(handle: DelayedCall) → bool

Remove an alarm.

Returns True if the alarm exists, False otherwise

remove_enter_idle(handle: int) → bool

Remove an idle callback.

Returns True if the handle was removed.

remove_watch_file(handle: int) → bool

Remove an input file.

Returns True if the input file exists, False otherwise

run() → None

Start the event loop.

Exit the loop when any callback raises an exception. If ExitMainLoop is raised, exit cleanly.

Raises:

BaseException – the exception that stopped the loop, once the loop has been left.

run_in_executor(executor: Executor, func: Callable[_Spec, _T], *args: _Spec.args, **kwargs: _Spec.kwargs) → Future[_T] | asyncio.Future[_T]

Raise NotImplementedError: use Twisted’s own thread pool API.

Raises:

NotImplementedError – Twisted has its own thread pool; use threads.deferToThread instead.

watch_file(fd: int, callback: Callable[[], _T]) → int

Call callback() when fd has some data to read.

No parameters are passed to callback. Returns a handle that may be passed to remove_watch_file().

Parameters:
  • fd – file descriptor to watch for input

  • callback – function to call when input is available

TornadoEventLoop

class urwid.TornadoEventLoop(loop: IOLoop | None = None)

This is an Urwid-specific event loop to plug into its MainLoop.

It acts as an adaptor for Tornado’s IOLoop which does all heavy lifting except idle-callbacks.

Note

alarm(), watch_file() and enter_idle() accept an async def callback in addition to a plain callable. A coroutine function is scheduled as an asyncio.Task on the IOLoop’s underlying asyncio loop instead of being called directly.

Wrap loop, or Tornado’s current IOLoop when none is given.

alarm(seconds: float, callback: Callable[[], Any]) → object

Schedule callback to run after seconds and return a handle for remove_alarm().

enter_idle(callback: Callable[[], Any]) → int

Add a callback for entering idle.

Returns a handle that may be passed to remove_idle()

handle_exit(f: Callable[_Spec, _T]) → Callable[_Spec, _T | Literal[False] | None]

Wrap f so that a raised exception stops the loop instead of propagating.

remove_alarm(handle: object) → bool

Cancel an alarm scheduled by alarm(), returning whether it was still pending.

remove_enter_idle(handle: int) → bool

Remove an idle callback.

Returns True if the handle was removed.

remove_watch_file(handle: int) → bool

Stop watching a file descriptor registered by watch_file(), returning whether it was watched.

run() → None

Start the event loop and run it until ExitMainLoop is raised.

Raises:

BaseException – the exception that stopped the loop, once the loop has been left.

run_in_executor(executor: Executor, func: Callable[_Spec, _T], *args: _Spec.args, **kwargs: _Spec.kwargs) → asyncio.Future[_T]

Run callable in executor.

Parameters:
  • executor – Executor to use for running the function

  • func – function to call

  • args – arguments to function (positional only)

  • kwargs – keyword arguments to function (keyword only)

Returns:

future object for the function call outcome.

watch_file(fd: int, callback: Callable[[], _T]) → int

Call callback whenever fd is readable and return a handle for remove_watch_file().

ZMQEventLoop

class urwid.ZMQEventLoop

This class is an urwid event loop for ZeroMQ applications.

It is very similar to SelectEventLoop, supporting the usual alarm() events and file watching (watch_file()) capabilities, but also incorporates the ability to watch zmq queues for events (watch_queue()).

Note

alarm(), watch_file(), watch_queue() and enter_idle() accept an async def callback in addition to a plain callable. ZMQEventLoop runs on top of an asyncio loop (via zmq.asyncio.Poller), so a coroutine function is scheduled as a background task there instead of being called directly, the same way it would be on any other asyncio-backed event loop.

Initialize with a fresh zmq poller and no alarms or watched queues yet.

alarm(seconds: float, callback: Callable[[], Any]) → ZMQAlarmHandle

Call callback a given time from now.

No parameters are passed to callback. Returns a handle that may be passed to remove_alarm().

Parameters:
  • seconds (float) – floating point time to wait before calling callback.

  • callback – function to call from event loop.

enter_idle(callback: Callable[[], Any]) → int

Add a callback to be executed when the event loop detects it is idle.

Returns a handle that may be passed to remove_enter_idle().

remove_alarm(handle: ZMQAlarmHandle) → bool

Remove an alarm.

Returns True if the alarm exists, False otherwise.

remove_enter_idle(handle: int) → bool

Remove an idle callback.

Returns True if handle was removed, False otherwise.

remove_watch_file(handle: int | SupportsFileno) → bool

Remove a file from background polling.

Returns True if the file was being monitored, False otherwise.

remove_watch_queue(handle: Socket[Any]) → bool

Remove a queue from background polling.

Returns True if the queue was being monitored, False otherwise.

run() → None

Start the event loop.

Exit the loop when any callback raises an exception. If ExitMainLoop is raised, exit cleanly.

Raises:

BaseException – the exception that stopped the loop, once the loop has been left.

run_in_executor(executor: Executor, func: Callable[_Spec, _T], *args: _Spec.args, **kwargs: _Spec.kwargs) → Future[_T]

Run callable in executor.

Parameters:
  • executor – Executor to use for running the function

  • func – function to call

  • args – positional arguments to function

  • kwargs – keyword arguments to function

Returns:

future object for the function call outcome.

watch_file(fd: int | SupportsFileno, callback: Callable[[], typing.Any], flags: int = <PollEvent.POLLIN: 1>) → int | SupportsFileno

Call callback when fd has some data to read.

No parameters are passed to the callback. The flags are as for watch_queue(). Returns a handle that may be passed to remove_watch_file().

Parameters:
  • fd – The file-like object, or fileno to monitor.

  • callback – The function to call when the file has data available.

  • flags (int) – The condition to monitor on the file (defaults to POLLIN).

watch_queue(queue: zmq.Socket[typing.Any], callback: Callable[[], typing.Any], flags: int = <PollEvent.POLLIN: 1>) → zmq.Socket[Any]

Call callback when zmq queue becomes ready to read or write.

flags controls the condition: POLLIN (the default) watches for data to read, POLLOUT watches for availability to write. No parameters are passed to the callback. Returns a handle that may be passed to remove_watch_queue().

Parameters:
  • queue – The zmq queue to poll.

  • callback – The function to call when the poll is successful.

  • flags (int) – The condition to monitor on the queue (defaults to POLLIN).

Raises:

ValueError – queue is already being watched.