0
# Utilities and Helpers
1
2
Additional utilities including asynchronous operations, timeouts, background threads, decorators, and low-level helpers for advanced RPyC usage. These utilities extend RPyC's core functionality with convenience features and advanced patterns.
3
4
## Capabilities
5
6
### Asynchronous Utilities
7
8
Tools for non-blocking remote operations and asynchronous programming patterns.
9
10
```python { .api }
11
def async_(proxy):
12
"""
13
Convert synchronous proxy calls to asynchronous operations.
14
15
Parameters:
16
- proxy: RPyC proxy object (netref)
17
18
Returns:
19
_Async: Async wrapper for proxy
20
21
Usage:
22
async_func = async_(conn.root.slow_function)
23
result = async_func(args) # Returns AsyncResult
24
"""
25
26
class _Async:
27
"""
28
Asynchronous wrapper for proxy objects.
29
"""
30
31
def __call__(self, *args, **kwargs):
32
"""
33
Call wrapped function asynchronously.
34
35
Returns:
36
AsyncResult: Async result container
37
"""
38
```
39
40
### Timeout and Timing Utilities
41
42
Decorators and utilities for adding timeouts and timing to operations.
43
44
```python { .api }
45
def timed(timeout, func):
46
"""
47
Add timeout to function calls.
48
49
Parameters:
50
- timeout (float): Timeout in seconds
51
- func (callable): Function to wrap
52
53
Returns:
54
callable: Function with timeout applied
55
"""
56
57
class timed:
58
"""
59
Timeout decorator class for adding timeouts to operations.
60
"""
61
62
def __init__(self, timeout):
63
"""
64
Initialize timeout decorator.
65
66
Parameters:
67
- timeout (float): Timeout in seconds
68
"""
69
70
def __call__(self, func):
71
"""Apply timeout to function"""
72
```
73
74
### Background Service Threads
75
76
Utilities for running RPyC services in background threads.
77
78
```python { .api }
79
class BgServingThread:
80
"""
81
Background thread for serving RPyC connections.
82
Allows main thread to continue while serving requests.
83
"""
84
85
def __init__(self, conn, callback=None):
86
"""
87
Initialize background serving thread.
88
89
Parameters:
90
- conn: RPyC connection to serve
91
- callback (callable): Optional callback for exceptions
92
"""
93
94
def start(self):
95
"""Start the background serving thread"""
96
97
def stop(self):
98
"""Stop the background serving thread"""
99
100
@property
101
def active(self) -> bool:
102
"""True if thread is active"""
103
```
104
105
### Iterator and Collection Utilities
106
107
Utilities for working with remote iterators and collections.
108
109
```python { .api }
110
def buffiter(obj, chunk=10, max_chunk=1000, factor=2):
111
"""
112
Buffered iterator for remote sequences.
113
Reduces network round-trips by fetching chunks.
114
115
Parameters:
116
- obj: Remote iterable object
117
- chunk (int): Initial chunk size
118
- max_chunk (int): Maximum chunk size
119
- factor (int): Chunk size growth factor
120
121
Yields:
122
Items from remote iterable in buffered chunks
123
"""
124
```
125
126
### Security and Access Control
127
128
Utilities for restricting and controlling access to objects.
129
130
```python { .api }
131
def restricted(obj, attrs, wattrs=None):
132
"""
133
Create restricted proxy with limited attribute access.
134
135
Parameters:
136
- obj: Object to restrict
137
- attrs (set): Allowed read attributes
138
- wattrs (set): Allowed write attributes (optional)
139
140
Returns:
141
Restricted proxy object
142
"""
143
```
144
145
### Service Decorators
146
147
Decorators for defining and configuring RPyC services.
148
149
```python { .api }
150
def exposed(func):
151
"""
152
Decorator marking methods as exposed to remote calls.
153
154
Parameters:
155
- func (callable): Function to expose
156
157
Returns:
158
callable: Exposed function
159
160
Usage:
161
@exposed
162
def my_method(self):
163
return "Available remotely"
164
"""
165
166
def service(cls):
167
"""
168
Class decorator for processing RPyC service classes.
169
Automatically renames exposed methods with proper prefix.
170
171
Parameters:
172
- cls: Service class to process
173
174
Returns:
175
class: Processed service class
176
177
Usage:
178
@service
179
class MyService(rpyc.Service):
180
@exposed
181
def my_method(self):
182
return "Hello"
183
"""
184
```
185
186
### Low-level Utilities
187
188
Low-level helper functions for advanced RPyC usage and debugging.
189
190
```python { .api }
191
def setup_logger(quiet=False, logfile=None, namespace=None):
192
"""
193
Setup RPyC logging configuration.
194
195
Parameters:
196
- quiet (bool): Reduce log verbosity if True
197
- logfile (str): Log to file if specified
198
- namespace (str): Logger namespace
199
200
Returns:
201
Logger: Configured logger instance
202
"""
203
204
def safe_import(name):
205
"""
206
Safely import module with fallback.
207
208
Parameters:
209
- name (str): Module name to import
210
211
Returns:
212
Module or MissingModule: Imported module or placeholder
213
"""
214
215
def spawn(*args, **kwargs):
216
"""
217
Start daemon thread with function and arguments.
218
219
Parameters:
220
- args[0] (callable): Function to run in thread
221
- args[1:]: Arguments for function
222
- kwargs: Keyword arguments for function
223
224
Returns:
225
Thread: Started daemon thread
226
"""
227
228
def get_id_pack(obj):
229
"""
230
Get ID pack for object (used internally for netrefs).
231
232
Parameters:
233
- obj: Object to get ID pack for
234
235
Returns:
236
tuple: Object identification tuple
237
"""
238
239
def get_methods(obj_attrs, obj):
240
"""
241
Get all methods of an object.
242
243
Parameters:
244
- obj_attrs (dict): Object attributes
245
- obj: Object to introspect
246
247
Returns:
248
list: List of (method_name, docstring) tuples
249
"""
250
```
251
252
### Threading Utilities
253
254
Advanced threading utilities for RPyC applications.
255
256
```python { .api }
257
def spawn_waitready(init, main):
258
"""
259
Start thread with initialization phase.
260
261
Parameters:
262
- init (callable): Initialization function
263
- main (callable): Main function to run after init
264
265
Returns:
266
tuple: (thread, init_result)
267
"""
268
269
class hybridmethod:
270
"""
271
Decorator for methods that work as both instance and class methods.
272
"""
273
274
def __init__(self, func):
275
"""
276
Initialize hybrid method decorator.
277
278
Parameters:
279
- func (callable): Function to wrap
280
"""
281
```
282
283
### Compatibility and Platform Utilities
284
285
Utilities for cross-platform and version compatibility.
286
287
```python { .api }
288
def hasattr_static(obj, attr):
289
"""
290
Check if object has attribute using static introspection.
291
292
Parameters:
293
- obj: Object to check
294
- attr (str): Attribute name
295
296
Returns:
297
bool: True if object has attribute
298
"""
299
300
class MissingModule:
301
"""
302
Placeholder for missing/unavailable modules.
303
"""
304
305
def __init__(self, name):
306
"""
307
Initialize missing module placeholder.
308
309
Parameters:
310
- name (str): Module name
311
"""
312
313
def __getattr__(self, name):
314
"""Raise ImportError for any attribute access"""
315
316
def __bool__(self):
317
"""Always returns False"""
318
```
319
320
## Examples
321
322
### Asynchronous Operations
323
324
```python
325
import rpyc
326
from rpyc.utils.helpers import async_
327
328
# Connect to server
329
conn = rpyc.connect('localhost', 12345)
330
331
# Make async calls
332
async_func = async_(conn.root.slow_computation)
333
result1 = async_func(data1)
334
result2 = async_func(data2)
335
336
# Do other work while computations run
337
print("Computations started...")
338
339
# Wait for results
340
print("Result 1:", result1.value)
341
print("Result 2:", result2.value)
342
343
conn.close()
344
```
345
346
### Background Serving
347
348
```python
349
import rpyc
350
from rpyc.utils.helpers import BgServingThread
351
import time
352
353
# Connect to server
354
conn = rpyc.connect('localhost', 12345)
355
356
# Start background serving
357
bg_thread = BgServingThread(conn)
358
bg_thread.start()
359
360
try:
361
# Main thread can do other work
362
# while background thread serves requests
363
for i in range(10):
364
result = conn.root.get_data(i)
365
print(f"Got result: {result}")
366
time.sleep(1)
367
368
finally:
369
# Clean up
370
bg_thread.stop()
371
conn.close()
372
```
373
374
### Buffered Iteration
375
376
```python
377
import rpyc
378
from rpyc.utils.helpers import buffiter
379
380
conn = rpyc.connect('localhost', 12345)
381
382
# Get remote large list
383
remote_list = conn.root.get_large_dataset()
384
385
# Iterate efficiently with buffering
386
for item in buffiter(remote_list, chunk=100):
387
process(item)
388
389
conn.close()
390
```
391
392
### Restricted Access
393
394
```python
395
import rpyc
396
from rpyc.utils.helpers import restricted
397
398
conn = rpyc.connect('localhost', 12345)
399
400
# Get remote object
401
remote_obj = conn.root.get_object()
402
403
# Create restricted version
404
safe_obj = restricted(
405
remote_obj,
406
attrs={'read_data', 'get_info'}, # Only these methods allowed
407
wattrs={'status'} # Only this attribute writable
408
)
409
410
# safe_obj only allows specified operations
411
data = safe_obj.read_data() # OK
412
info = safe_obj.get_info() # OK
413
safe_obj.status = 'active' # OK
414
# safe_obj.delete_all() # Would raise AttributeError
415
416
conn.close()
417
```
418
419
### Service Definition with Decorators
420
421
```python
422
import rpyc
423
from rpyc.utils import exposed, service
424
425
@service
426
class CalculatorService(rpyc.Service):
427
def __init__(self):
428
self.history = []
429
430
@exposed
431
def add(self, a, b):
432
result = a + b
433
self.history.append(f"{a} + {b} = {result}")
434
return result
435
436
@exposed
437
def get_history(self):
438
return self.history.copy()
439
440
def _internal_method(self):
441
# Not exposed - private method
442
pass
443
444
# Service automatically processes exposed methods
445
from rpyc.utils.server import ThreadedServer
446
server = ThreadedServer(CalculatorService, port=12345)
447
server.start()
448
```
449
450
### Timeout Operations
451
452
```python
453
import rpyc
454
from rpyc.utils.helpers import timed
455
456
conn = rpyc.connect('localhost', 12345)
457
458
# Add timeout to remote function
459
timed_func = timed(5.0, conn.root.slow_function)
460
461
try:
462
result = timed_func(args)
463
print("Completed within timeout:", result)
464
except Exception as e:
465
print("Function timed out or failed:", e)
466
467
conn.close()
468
```
469
470
### Custom Logging
471
472
```python
473
import rpyc
474
from rpyc.lib import setup_logger
475
476
# Setup detailed logging
477
logger = setup_logger(quiet=False, logfile='rpyc.log')
478
479
# RPyC operations will now be logged
480
conn = rpyc.connect('localhost', 12345)
481
logger.info("Connected to server")
482
483
result = conn.root.some_function()
484
logger.info(f"Function result: {result}")
485
486
conn.close()
487
logger.info("Connection closed")
488
```
489
490
### Safe Module Import
491
492
```python
493
from rpyc.lib import safe_import
494
495
# Safely import optional modules
496
ssl = safe_import('ssl')
497
if ssl:
498
# SSL is available
499
print("SSL support available")
500
else:
501
# SSL not available, ssl is MissingModule
502
print("SSL not available")
503
504
# Using the imported module
505
try:
506
context = ssl.create_default_context()
507
except ImportError:
508
print("SSL operations not supported")
509
```
510
511
## Constants
512
513
```python { .api }
514
SPAWN_THREAD_PREFIX = 'RpycSpawnThread' # Prefix for spawned thread names
515
```