class StoppableThread
A custom thread class that extends threading.Thread with the ability to gracefully stop a Bokeh server running in the thread by stopping its IOLoop.
/tf/active/vicechatdev/patches/server.py
760 - 786
moderate
Purpose
StoppableThread provides a mechanism to run Bokeh server instances in separate threads with proper cleanup capabilities. It wraps the standard threading.Thread functionality and adds a stop() method that can gracefully shut down the Bokeh server and its associated Tornado IOLoop. This is particularly useful for managing Bokeh server lifecycles in applications that need to start and stop servers programmatically, such as in testing environments or dynamic server management scenarios.
Source Code
class StoppableThread(threading.Thread):
"""Thread class with a stop() method."""
def __init__(self, io_loop=None, **kwargs):
super().__init__(**kwargs)
self.io_loop = io_loop
def run(self):
if hasattr(self, '_target'):
target, args, kwargs = self._target, self._args, self._kwargs
else:
target, args, kwargs = self._Thread__target, self._Thread__args, self._Thread__kwargs
if not target:
return
bokeh_server = None
try:
bokeh_server = target(*args, **kwargs)
finally:
if isinstance(bokeh_server, Server):
bokeh_server.stop()
if hasattr(self, '_target'):
del self._target, self._args, self._kwargs
else:
del self._Thread__target, self._Thread__args, self._Thread__kwargs
def stop(self):
self.io_loop.add_callback(self.io_loop.stop)
Parameters
| Name | Type | Default | Kind |
|---|---|---|---|
bases |
threading.Thread | - |
Parameter Details
io_loop: A Tornado IOLoop instance that will be used to stop the thread. This should be the same IOLoop that the Bokeh server is running on. If None, the stop() method will fail. This is typically obtained from the Bokeh Server instance.
**kwargs: Additional keyword arguments passed to the parent threading.Thread constructor. Common arguments include 'target' (the callable to run), 'args' (positional arguments for target), 'kwargs' (keyword arguments for target), 'name' (thread name), and 'daemon' (whether thread is a daemon).
Return Value
Instantiation returns a StoppableThread object that is a subclass of threading.Thread. The run() method returns None. The stop() method returns None but triggers the IOLoop to stop asynchronously via a callback.
Class Interface
Methods
__init__(self, io_loop=None, **kwargs)
Purpose: Initialize the StoppableThread with an IOLoop and pass additional arguments to the parent Thread class
Parameters:
io_loop: Tornado IOLoop instance for stopping the thread, defaults to None**kwargs: Additional keyword arguments for threading.Thread (target, args, kwargs, name, daemon, etc.)
Returns: None (constructor)
run(self)
Purpose: Override of Thread.run() that executes the target function and ensures proper cleanup of the Bokeh server and internal references
Returns: None, but may return early if no target is set
stop(self)
Purpose: Gracefully stop the thread by stopping the associated IOLoop via a callback
Returns: None, triggers asynchronous IOLoop stop
Attributes
| Name | Type | Description | Scope |
|---|---|---|---|
io_loop |
tornado.ioloop.IOLoop or None | The Tornado IOLoop instance used to stop the thread. Must be set for stop() to work properly. | instance |
_target |
callable or None | The callable object to be invoked by the run() method (Python 3.10+). Inherited from threading.Thread. | instance |
_args |
tuple | Positional arguments for the target callable (Python 3.10+). Inherited from threading.Thread. | instance |
_kwargs |
dict | Keyword arguments for the target callable (Python 3.10+). Inherited from threading.Thread. | instance |
_Thread__target |
callable or None | The callable object to be invoked by the run() method (Python < 3.10). Name-mangled attribute from threading.Thread. | instance |
_Thread__args |
tuple | Positional arguments for the target callable (Python < 3.10). Name-mangled attribute from threading.Thread. | instance |
_Thread__kwargs |
dict | Keyword arguments for the target callable (Python < 3.10). Name-mangled attribute from threading.Thread. | instance |
Dependencies
threadingbokehtornado
Required Imports
import threading
from bokeh.server.server import Server
from tornado.ioloop import IOLoop
Usage Example
from tornado.ioloop import IOLoop
from bokeh.server.server import Server
from bokeh.application import Application
# Define a function that creates and returns a Bokeh server
def create_server():
app = Application()
io_loop = IOLoop.current()
server = Server({'/': app}, io_loop=io_loop, port=5006)
server.start()
server.io_loop.start()
return server
# Create and start the stoppable thread
io_loop = IOLoop()
thread = StoppableThread(io_loop=io_loop, target=create_server)
thread.start()
# Later, stop the thread gracefully
thread.stop()
thread.join() # Wait for thread to finish
Best Practices
- Always provide an io_loop parameter during instantiation to enable the stop() method
- The target function should return a Bokeh Server instance for automatic cleanup
- Call thread.join() after stop() to ensure the thread has fully terminated before proceeding
- The thread automatically cleans up internal references to target, args, and kwargs after execution
- Handle both Python 3.10+ (_target) and older Python versions (_Thread__target) attribute naming
- The stop() method uses add_callback to ensure thread-safe stopping of the IOLoop
- If the target function doesn't return a Server instance, manual cleanup may be required
- Consider setting daemon=True if the thread should not prevent program exit
Similar Components
AI-powered semantic similarity - components with related functionality:
-
function async_execute 44.4% similar
-
class RootHandler 43.5% similar
-
class Application 41.7% similar
-
function run_smtp_server 41.5% similar
-
class periodic 40.1% similar