0
# Client and Server
1
2
Client-server functionality for building interactive web applications with real-time Python callbacks. Enables building standalone Bokeh applications that update dynamically based on user interactions, data changes, and server-side computations.
3
4
## Capabilities
5
6
### Application Framework
7
8
Core classes for creating Bokeh applications that run on the Bokeh server.
9
10
```python { .api }
11
class Application:
12
"""
13
Factory for creating Bokeh documents with handlers.
14
15
Applications define how to create documents for each client session,
16
enabling multi-user interactive applications.
17
"""
18
def __init__(self, *handlers, **kwargs):
19
"""
20
Parameters:
21
- handlers: ApplicationHandler objects that define document creation logic
22
- metadata: dict, application metadata
23
"""
24
25
def curdoc():
26
"""
27
Get the current document for server applications.
28
29
Returns the Document associated with the current Bokeh server session.
30
Essential for server applications to access and modify the document.
31
32
Returns:
33
Document: Current document instance
34
"""
35
```
36
37
### Client Session Management
38
39
Functions and classes for connecting to and managing Bokeh server sessions from client code.
40
41
```python { .api }
42
class ClientSession:
43
"""
44
Client session for connecting to a Bokeh server.
45
46
Manages the connection between client code and a running Bokeh server,
47
enabling programmatic control of server applications.
48
"""
49
def __init__(self, session_id=None, websocket_url=None, io_loop=None, **kwargs):
50
"""
51
Parameters:
52
- session_id: str, specific session identifier
53
- websocket_url: str, server websocket URL
54
- io_loop: IOLoop, Tornado IOLoop instance
55
"""
56
57
def push(self, document=None):
58
"""Push document changes to the server."""
59
60
def pull(self):
61
"""Pull document state from the server."""
62
63
def close(self, why="closed"):
64
"""Close the client session."""
65
66
def pull_session(session_id=None, url=None, io_loop=None):
67
"""
68
Pull an existing session from a Bokeh server.
69
70
Parameters:
71
- session_id: str, session identifier to pull
72
- url: str, server URL
73
- io_loop: IOLoop, Tornado IOLoop instance
74
75
Returns:
76
ClientSession: Connected client session
77
"""
78
79
def push_session(document, session_id=None, url=None, io_loop=None):
80
"""
81
Push a document to create a new server session.
82
83
Parameters:
84
- document: Document, document to push to server
85
- session_id: str, session identifier
86
- url: str, server URL
87
- io_loop: IOLoop, Tornado IOLoop instance
88
89
Returns:
90
ClientSession: Connected client session
91
"""
92
93
def show_session(session_id=None, url=None, browser=None, new=None):
94
"""
95
Display a server session in the browser.
96
97
Parameters:
98
- session_id: str, session identifier
99
- url: str, server URL
100
- browser: str, browser name to use
101
- new: int, browser window/tab behavior
102
"""
103
104
DEFAULT_SESSION_ID: str # Default session identifier
105
```
106
107
### Server Components
108
109
Core server infrastructure for running Bokeh server applications.
110
111
```python { .api }
112
class Server:
113
"""
114
Bokeh server for hosting interactive applications.
115
116
Runs Bokeh applications and serves them to web browsers,
117
handling multiple concurrent sessions and real-time updates.
118
"""
119
def __init__(self, applications=None, port=5006, address=None, **kwargs):
120
"""
121
Parameters:
122
- applications: dict, mapping of URL paths to Application objects
123
- port: int, server port number
124
- address: str, server bind address
125
- allow_websocket_origin: list, allowed websocket origins
126
- io_loop: IOLoop, Tornado IOLoop instance
127
"""
128
129
def start(self):
130
"""Start the Bokeh server."""
131
132
def stop(self):
133
"""Stop the Bokeh server."""
134
135
def io_loop(self):
136
"""Get the server's IOLoop."""
137
138
class BaseServer:
139
"""Base class for Bokeh server implementations."""
140
141
class BokehTornado:
142
"""Tornado-based Bokeh server implementation."""
143
```
144
145
### Document Lifecycle
146
147
Functions for managing document lifecycle in server applications.
148
149
```python { .api }
150
def without_document_lock(func):
151
"""
152
Decorator to execute function without document lock.
153
154
Used in server applications when modifying documents
155
from background threads or async callbacks.
156
157
Parameters:
158
- func: callable, function to execute without lock
159
160
Returns:
161
Decorated function
162
"""
163
164
class DocumentLock:
165
"""Document locking mechanism for thread safety."""
166
167
def __enter__(self):
168
"""Acquire document lock."""
169
170
def __exit__(self, exc_type, exc_val, exc_tb):
171
"""Release document lock."""
172
```
173
174
### Session State Management
175
176
Tools for managing application state across server sessions.
177
178
```python { .api }
179
class SessionContext:
180
"""Context information for server sessions."""
181
182
def __init__(self, server_context=None, session_id=None, **kwargs):
183
"""
184
Parameters:
185
- server_context: ServerContext, server context
186
- session_id: str, session identifier
187
"""
188
189
@property
190
def request(self):
191
"""Get the current HTTP request."""
192
193
@property
194
def session_id(self):
195
"""Get the session identifier."""
196
197
class ServerContext:
198
"""Server-level context information."""
199
200
def __init__(self, **kwargs):
201
"""
202
Parameters:
203
- sessions: dict, active sessions
204
- applications: dict, loaded applications
205
"""
206
```
207
208
### Periodic Callbacks
209
210
Functions for scheduling periodic updates in server applications.
211
212
```python { .api }
213
def add_periodic_callback(callback, period_milliseconds):
214
"""
215
Schedule a function to be called periodically.
216
217
Parameters:
218
- callback: callable, function to call periodically
219
- period_milliseconds: int, callback interval in milliseconds
220
221
Returns:
222
Callback handle for removing the periodic callback
223
"""
224
225
def remove_periodic_callback(callback_handle):
226
"""
227
Remove a periodic callback.
228
229
Parameters:
230
- callback_handle: handle returned by add_periodic_callback
231
"""
232
233
class PeriodicCallback:
234
"""Periodic callback wrapper."""
235
236
def __init__(self, callback, period, io_loop=None):
237
"""
238
Parameters:
239
- callback: callable, function to call
240
- period: int, callback period in milliseconds
241
- io_loop: IOLoop, Tornado IOLoop instance
242
"""
243
244
def start(self):
245
"""Start the periodic callback."""
246
247
def stop(self):
248
"""Stop the periodic callback."""
249
```
250
251
### Application Handlers
252
253
Handler classes for different types of Bokeh applications.
254
255
```python { .api }
256
class ApplicationHandler:
257
"""Base class for application handlers."""
258
259
def modify_document(self, doc):
260
"""Modify document when creating new sessions."""
261
262
class FunctionHandler(ApplicationHandler):
263
"""Handler that wraps a simple function."""
264
265
def __init__(self, func):
266
"""
267
Parameters:
268
- func: callable, function that modifies a document
269
"""
270
271
class ScriptHandler(ApplicationHandler):
272
"""Handler that executes a Python script."""
273
274
def __init__(self, filename=None, source=None, **kwargs):
275
"""
276
Parameters:
277
- filename: str, path to Python script file
278
- source: str, Python source code
279
"""
280
281
class DirectoryHandler(ApplicationHandler):
282
"""Handler for directory-based applications."""
283
284
def __init__(self, filename, **kwargs):
285
"""
286
Parameters:
287
- filename: str, path to application directory
288
"""
289
290
class NotebookHandler(ApplicationHandler):
291
"""Handler for Jupyter notebook applications."""
292
293
def __init__(self, filename, **kwargs):
294
"""
295
Parameters:
296
- filename: str, path to notebook file
297
"""
298
```
299
300
## Usage Examples
301
302
### Basic Server Application
303
304
```python
305
from bokeh.application import Application
306
from bokeh.application.handlers import FunctionHandler
307
from bokeh.server.server import Server
308
from bokeh.plotting import figure
309
from bokeh.models.widgets import Button
310
from bokeh.layouts import column
311
from bokeh.io import curdoc
312
313
def create_document(doc):
314
# Create plot
315
plot = figure(width=400, height=400)
316
plot.circle([1, 2, 3], [4, 5, 6], size=10)
317
318
# Create button
319
button = Button(label="Update Plot")
320
321
def button_callback():
322
# Update plot data
323
plot.circle([2, 3, 4], [5, 6, 7], size=15, color="red")
324
325
button.on_click(button_callback)
326
327
# Add to document
328
layout = column(button, plot)
329
doc.add_root(layout)
330
331
# Create application
332
app = Application(FunctionHandler(create_document))
333
334
# Start server
335
server = Server({'/': app}, port=5006)
336
server.start()
337
338
print("Server running on http://localhost:5006")
339
server.io_loop.add_callback(server.show, "/")
340
server.io_loop.start()
341
```
342
343
### Client Session Management
344
345
```python
346
from bokeh.client import push_session, pull_session
347
from bokeh.plotting import figure
348
from bokeh.io import curdoc
349
350
# Create a document
351
plot = figure()
352
plot.line([1, 2, 3], [4, 5, 6])
353
354
# Push to server
355
session = push_session(curdoc(), url="http://localhost:5006")
356
357
# Later, pull from server
358
session = pull_session(url="http://localhost:5006", session_id="specific_session")
359
print(f"Document title: {session.document.title}")
360
361
# Close session
362
session.close()
363
```
364
365
### Periodic Updates
366
367
```python
368
from bokeh.io import curdoc
369
from bokeh.plotting import figure
370
from bokeh.models import ColumnDataSource
371
import numpy as np
372
373
# Create plot with data source
374
source = ColumnDataSource(data=dict(x=[1, 2, 3], y=[4, 5, 6]))
375
plot = figure()
376
plot.circle('x', 'y', source=source, size=10)
377
378
def update_data():
379
# Generate new random data
380
new_data = dict(
381
x=np.random.random(10),
382
y=np.random.random(10)
383
)
384
source.data = new_data
385
386
# Add periodic callback (update every 1000ms)
387
curdoc().add_periodic_callback(update_data, 1000)
388
curdoc().add_root(plot)
389
```
390
391
### Multi-User Application State
392
393
```python
394
from bokeh.io import curdoc
395
from bokeh.models.widgets import TextInput, Div
396
from bokeh.layouts import column
397
398
# Shared application state
399
app_state = {"message_count": 0}
400
401
def create_session():
402
# Create per-session widgets
403
text_input = TextInput(title="Enter message:")
404
message_div = Div(text=f"Messages sent: {app_state['message_count']}")
405
406
def send_message(attr, old, new):
407
# Update shared state
408
app_state["message_count"] += 1
409
message_div.text = f"Messages sent: {app_state['message_count']}"
410
text_input.value = ""
411
412
text_input.on_change('value', send_message)
413
414
layout = column(text_input, message_div)
415
curdoc().add_root(layout)
416
417
create_session()
418
```
419
420
## Common Data Types
421
422
```python { .api }
423
# Server-related types
424
ServerContextLike = Union[ServerContext, None]
425
SessionContextLike = Union[SessionContext, None]
426
ApplicationLike = Union[Application, str, callable]
427
428
# Handler types
429
HandlerLike = Union[ApplicationHandler, str, callable]
430
ModifyDocumentCallable = Callable[[Document], None]
431
432
# Session types
433
SessionIdLike = Union[str, None]
434
URLLike = Union[str, None]
435
IOLoopLike = Union[Any, None] # Tornado IOLoop type
436
```