Traits Futures: reactive background processing for Traits and TraitsUI¶
Release v1.1.
The traits_futures
package provides a means to fire off a background
calculation from a TraitsUI application, and later respond to the result(s)
of that calculation, leaving the main UI responsive for user interactions while
the background calculation is in progress.
Features¶
Supports simple calls, iterations, and progress-reporting functions. Can easily be extended to support other messaging patterns.
Dispatching a background task returns a “future” object, which provides:
information about state changes (e.g., background task completion)
facilities to (cooperatively) cancel a long-running background task
access to result(s) arriving from the background task
Future objects are
HasTraits
instances, suitable for integration into a TraitsUI application.No need to be a threading expert! Incoming results arrive as trait changes in the main thread. This eliminates a large class of potential issues with traditional thread-based solutions (race conditions, deadlocks, and UI updates off the main thread).
Cross-platform.
Limitations¶
By design, and unlike
concurrent.futures
,traits_futures
requires the UI event loop to be running in order to process results.Requires Python 3.8 or later.
Quick start¶
Here’s a complete example
showing a
minimal TraitsUI application that fires off a background computation when its
“Calculate” button is pressed, and shows the result when it arrives.
import time
from traits.api import (
Bool,
Button,
HasStrictTraits,
Instance,
Int,
observe,
Property,
Str,
)
from traits_futures.api import CallFuture, submit_call, TraitsExecutor
from traitsui.api import Item, UItem, View
def slow_square(n):
"""Square the given input, slowly."""
time.sleep(5.0)
return n * n
class QuickStartExample(HasStrictTraits):
#: The executor to submit tasks to.
traits_executor = Instance(TraitsExecutor)
#: The future object returned on task submission.
future = Instance(CallFuture)
#: Input for the calculation.
input = Int(10)
#: Copy of the input for the last-run / currently-running calculation.
input_for_calculation = Int()
#: Message about state of calculation.
message = Str("No previous calculation runs")
#: Button to start the calculation.
calculate = Button()
#: Boolean used to decide whether to enable the "calculate" button.
no_running_future = Property(Bool(), observe="future:done")
@observe("calculate")
def _submit_background_call(self, event):
# Returns immediately.
input = self.input
self.input_for_calculation = self.input
self.message = "Calculating square of {} ...".format(input)
self.future = submit_call(self.traits_executor, slow_square, input)
# Keep a record so that we can present messages accurately.
self.input_for_calculation = input
@observe("future:done")
def _report_result(self, event):
future = event.object
self.message = "The square of {} is {}.".format(
self.input_for_calculation, future.result
)
def _get_no_running_future(self):
return self.future is None or self.future.done
traits_view = View(
Item("input"),
UItem("message", style="readonly"),
UItem("calculate", enabled_when="no_running_future"),
resizable=True,
)
if __name__ == "__main__":
traits_executor = TraitsExecutor()
try:
QuickStartExample(traits_executor=traits_executor).configure_traits()
finally:
traits_executor.shutdown()
User Guide¶
API Documentation¶
- traits_futures package
- traits_futures.api module
- traits_futures.background_call module
- traits_futures.background_iteration module
- traits_futures.background_progress module
- traits_futures.base_future module
- traits_futures.ets_event_loop module
- traits_futures.exception_handling module
- traits_futures.executor_states module
- traits_futures.future_states module
- traits_futures.i_event_loop module
- traits_futures.i_event_loop_helper module
- traits_futures.i_message_router module
- traits_futures.i_parallel_context module
- traits_futures.i_pingee module
- traits_futures.i_task_specification module
- traits_futures.multiprocessing_context module
- traits_futures.multiprocessing_router module
- traits_futures.multithreading_context module
- traits_futures.multithreading_router module
- traits_futures.traits_executor module
- traits_futures.wrappers module
- traits_futures.asyncio package
- traits_futures.qt package
- traits_futures.testing package
- traits_futures.wx package