0
# Services and Protocols
1
2
Service classes for defining remote interfaces and protocol management for handling RPyC connections. Services define what methods and objects are exposed across connections, while the protocol layer handles the low-level communication and object proxying.
3
4
## Capabilities
5
6
### Base Service Classes
7
8
Core service classes that define the interface between local and remote objects.
9
10
```python { .api }
11
class Service:
12
"""
13
Base class for RPyC services. Override methods to create custom services.
14
"""
15
16
def on_connect(self, conn):
17
"""Called when client connects"""
18
19
def on_disconnect(self, conn):
20
"""Called when client disconnects"""
21
22
def exposed_get_service_name(self):
23
"""Returns the service name"""
24
25
def exposed_get_service_aliases(self):
26
"""Returns list of service aliases"""
27
28
class VoidService(Service):
29
"""
30
Empty service that exposes no methods. Used as default service.
31
"""
32
```
33
34
### Specialized Service Classes
35
36
Pre-built service classes for common distributed computing patterns.
37
38
```python { .api }
39
class SlaveService(Service):
40
"""
41
Service that provides access to the local namespace and modules.
42
Used in classic mode for remote Python execution.
43
"""
44
45
def exposed_execute(self, code):
46
"""Execute Python code remotely"""
47
48
def exposed_eval(self, expression):
49
"""Evaluate Python expression remotely"""
50
51
def exposed_getattr(self, obj, name):
52
"""Get attribute from remote object"""
53
54
def exposed_setattr(self, obj, name, value):
55
"""Set attribute on remote object"""
56
57
class MasterService(Service):
58
"""
59
Service that provides master-side functionality for distributed computing.
60
"""
61
62
class ClassicService(MasterService, SlaveService):
63
"""
64
Combined service providing both master and slave functionality.
65
Used for symmetric connections where both sides can execute code.
66
"""
67
```
68
69
### Connection Management
70
71
The Connection class manages the protocol-level communication and object proxying.
72
73
```python { .api }
74
class Connection:
75
"""
76
Represents an RPyC connection, handling protocol communication and object proxying.
77
"""
78
79
def __init__(self, service, channel, config=None):
80
"""
81
Initialize connection.
82
83
Parameters:
84
- service (Service): Local service instance
85
- channel: Communication channel
86
- config (dict): Configuration dictionary
87
"""
88
89
@property
90
def root(self):
91
"""Access to remote service's root namespace"""
92
93
@property
94
def closed(self) -> bool:
95
"""True if connection is closed"""
96
97
def close(self):
98
"""Close the connection"""
99
100
def ping(self, data=None, timeout=3):
101
"""
102
Ping remote side to test connectivity.
103
104
Parameters:
105
- data: Optional data to send with ping
106
- timeout (float): Ping timeout in seconds
107
108
Returns:
109
data: Echo of sent data
110
"""
111
112
def serve(self, timeout=1):
113
"""
114
Serve incoming requests for specified time.
115
116
Parameters:
117
- timeout (float): Time to serve requests
118
"""
119
120
def serve_all(self):
121
"""Serve all pending requests"""
122
123
def serve_forever(self):
124
"""Serve requests indefinitely"""
125
126
def poll_all(self, timeout=0):
127
"""
128
Poll and handle all pending requests.
129
130
Parameters:
131
- timeout (float): Polling timeout
132
133
Returns:
134
bool: True if requests were handled
135
"""
136
```
137
138
### Network References (Netrefs)
139
140
Network references provide transparent proxying of remote objects.
141
142
```python { .api }
143
class BaseNetref:
144
"""
145
Base class for network references - transparent proxies to remote objects.
146
"""
147
148
def __getattr__(self, name):
149
"""Get attribute from remote object"""
150
151
def __setattr__(self, name, value):
152
"""Set attribute on remote object"""
153
154
def __call__(self, *args, **kwargs):
155
"""Call remote object if callable"""
156
157
def __str__(self):
158
"""String representation of remote object"""
159
160
def __repr__(self):
161
"""Detailed representation of remote object"""
162
```
163
164
### Asynchronous Operations
165
166
Support for non-blocking remote operations.
167
168
```python { .api }
169
class AsyncResult:
170
"""
171
Container for asynchronous operation results.
172
"""
173
174
@property
175
def ready(self) -> bool:
176
"""True if result is ready"""
177
178
@property
179
def expired(self) -> bool:
180
"""True if result has expired"""
181
182
def wait(self, timeout=None):
183
"""
184
Wait for result to be ready.
185
186
Parameters:
187
- timeout (float): Maximum time to wait
188
189
Raises:
190
AsyncResultTimeout: If timeout exceeded
191
"""
192
193
@property
194
def value(self):
195
"""Get the result value (blocks if not ready)"""
196
197
class AsyncResultTimeout(Exception):
198
"""Raised when async operations timeout"""
199
```
200
201
### Configuration
202
203
Default configuration options for RPyC connections.
204
205
```python { .api }
206
DEFAULT_CONFIG = {
207
'allow_all_attrs': False,
208
'allow_pickle': False,
209
'allow_getattr': True,
210
'allow_setattr': False,
211
'allow_delattr': False,
212
'allow_public_attrs': True,
213
'exposed_prefix': 'exposed_',
214
'allow_safe_attrs': True,
215
'safe_attrs': frozenset(['__abs__', '__add__', '__and__', '__bool__', '__cmp__',
216
'__contains__', '__div__', '__divmod__', '__doc__', '__eq__',
217
'__float__', '__floordiv__', '__ge__', '__getitem__',
218
'__gt__', '__hash__', '__hex__', '__iadd__', '__iand__',
219
'__idiv__', '__ifloordiv__', '__ilshift__', '__imod__',
220
'__imul__', '__int__', '__invert__', '__ior__', '__ipow__',
221
'__irshift__', '__isub__', '__iter__', '__itruediv__',
222
'__ixor__', '__le__', '__len__', '__long__', '__lshift__',
223
'__lt__', '__mod__', '__mul__', '__ne__', '__neg__',
224
'__next__', '__oct__', '__or__', '__pos__', '__pow__',
225
'__radd__', '__rand__', '__rdiv__', '__rdivmod__',
226
'__repr__', '__rfloordiv__', '__rlshift__', '__rmod__',
227
'__rmul__', '__ror__', '__rpow__', '__rrshift__',
228
'__rshift__', '__rsub__', '__rtruediv__', '__rxor__',
229
'__setitem__', '__str__', '__sub__', '__truediv__',
230
'__xor__', 'next']),
231
'instantiate_custom_exceptions': False,
232
'instantiate_oldstyle_exceptions': False,
233
'propagate_SystemExit_locally': False,
234
'propagate_KeyboardInterrupt_locally': False,
235
'logger': None,
236
'connid': None,
237
'credentials': None,
238
'endpoints_timeout': 3,
239
'sync_request_timeout': 30,
240
}
241
```
242
243
## Examples
244
245
### Creating Custom Services
246
247
```python
248
import rpyc
249
from rpyc import exposed
250
251
class CalculatorService(rpyc.Service):
252
"""Custom service providing calculator functionality"""
253
254
@exposed
255
def add(self, a, b):
256
return a + b
257
258
@exposed
259
def multiply(self, a, b):
260
return a * b
261
262
@exposed
263
def get_history(self):
264
# Could return calculation history
265
return []
266
267
def on_connect(self, conn):
268
print(f"Client connected: {conn}")
269
270
def on_disconnect(self, conn):
271
print(f"Client disconnected: {conn}")
272
273
# Use the service
274
from rpyc.utils.server import ThreadedServer
275
server = ThreadedServer(CalculatorService, port=12345)
276
server.start()
277
```
278
279
### Using Connections with Custom Configuration
280
281
```python
282
import rpyc
283
284
# Custom configuration
285
config = {
286
'allow_pickle': True, # Allow pickle serialization
287
'sync_request_timeout': 60, # 60 second timeout
288
}
289
290
# Connect with custom config
291
conn = rpyc.connect('localhost', 12345, config=config)
292
293
# Use connection
294
result = conn.root.some_function()
295
conn.close()
296
```
297
298
### Asynchronous Operations
299
300
```python
301
import rpyc
302
303
conn = rpyc.connect('localhost', 12345)
304
305
# Start async operation
306
async_result = rpyc.async_(conn.root.long_running_function)()
307
308
# Do other work while operation runs
309
print("Operation started, doing other work...")
310
311
# Wait for result
312
try:
313
result = async_result.wait(timeout=30)
314
print(f"Result: {async_result.value}")
315
except rpyc.AsyncResultTimeout:
316
print("Operation timed out")
317
318
conn.close()
319
```
320
321
### Connection Lifecycle Management
322
323
```python
324
import rpyc
325
326
# Connect and manage lifecycle
327
conn = rpyc.connect('localhost', 12345)
328
329
try:
330
# Test connectivity
331
conn.ping()
332
333
# Use connection
334
result = conn.root.get_data()
335
336
# Serve any pending requests
337
conn.serve_all()
338
339
finally:
340
# Always close connection
341
conn.close()
342
```
343
344
## Exceptions
345
346
```python { .api }
347
class GenericException(Exception):
348
"""Wrapper for remote exceptions"""
349
350
class PingError(Exception):
351
"""Raised when connection ping fails"""
352
```