0
# Exception Handling
1
2
pyparted provides comprehensive exception handling with specific exception types for different error conditions. The exception system includes both high-level Python exceptions and low-level libparted exception handling.
3
4
## Capabilities
5
6
### Exception Classes
7
8
Specific exception types for different categories of errors.
9
10
```python { .api }
11
# Core operation exceptions
12
class AlignmentException(Exception):
13
"""Raised when alignment operations fail."""
14
15
class ConstraintException(Exception):
16
"""Raised when constraint operations fail or constraints cannot be satisfied."""
17
18
class CreateException(Exception):
19
"""Raised when object creation fails."""
20
21
class DeviceException(Exception):
22
"""Raised when device operations fail."""
23
24
class DiskException(Exception):
25
"""Raised when disk operations fail."""
26
27
class DiskLabelException(Exception):
28
"""Raised when disk label operations fail."""
29
30
class FileSystemException(Exception):
31
"""Raised when filesystem operations fail."""
32
33
class GeometryException(Exception):
34
"""Raised when geometry operations fail."""
35
36
class IOException(Exception):
37
"""Raised when I/O operations fail."""
38
39
class PartitionException(Exception):
40
"""Raised when partition operations fail."""
41
42
class TimerException(Exception):
43
"""Raised when timer operations fail."""
44
45
# Discovery exceptions
46
class UnknownDeviceException(Exception):
47
"""Raised when device cannot be identified."""
48
49
class UnknownTypeException(Exception):
50
"""Raised when type cannot be identified or is invalid."""
51
52
# General exceptions
53
class PartedException(Exception):
54
"""General pyparted exception base class."""
55
56
class NotNeededException(Exception):
57
"""Raised when operation is not needed."""
58
59
# Property access exceptions
60
class ReadOnlyProperty(Exception):
61
"""Raised when attempting to write to read-only property."""
62
63
class WriteOnlyProperty(Exception):
64
"""Raised when attempting to read from write-only property."""
65
```
66
67
### Exception Handler Functions
68
69
Functions for managing low-level libparted exception handling.
70
71
```python { .api }
72
def register_exn_handler(handler_function) -> None:
73
"""
74
Register custom exception handler for libparted exceptions.
75
76
Args:
77
handler_function: Function that takes (exception_type, message, options)
78
and returns resolution constant
79
"""
80
81
def clear_exn_handler() -> None:
82
"""
83
Clear registered exception handler, reverting to default handling.
84
"""
85
```
86
87
## Usage Examples
88
89
### Basic Exception Handling
90
91
```python
92
import parted
93
94
def safe_device_access(device_path):
95
"""Safely access device with proper exception handling."""
96
try:
97
device = parted.getDevice(device_path)
98
print(f"Device: {device.model}")
99
return device
100
101
except parted.DeviceException as e:
102
print(f"Device error: {e}")
103
return None
104
except parted.UnknownDeviceException as e:
105
print(f"Unknown device: {e}")
106
return None
107
except Exception as e:
108
print(f"Unexpected error: {e}")
109
return None
110
111
# Test with valid and invalid paths
112
devices_to_test = ['/dev/sda', '/dev/nonexistent', '/invalid/path']
113
for device_path in devices_to_test:
114
result = safe_device_access(device_path)
115
print(f"{device_path}: {'Success' if result else 'Failed'}\n")
116
```
117
118
### Comprehensive Disk Operations with Exception Handling
119
120
```python
121
import parted
122
123
def safe_disk_operations(device_path):
124
"""Perform disk operations with comprehensive error handling."""
125
try:
126
# Get device
127
device = parted.getDevice(device_path)
128
print(f"Found device: {device.model}")
129
130
# Read disk
131
try:
132
disk = parted.newDisk(device)
133
print(f"Disk type: {disk.type}")
134
135
# List partitions
136
for partition in disk.partitions:
137
try:
138
size = partition.getSize('GB')
139
print(f"Partition {partition.number}: {size:.1f} GB")
140
141
# Check flags safely
142
if partition.isFlagAvailable(parted.PARTITION_BOOT):
143
boot_flag = partition.getFlag(parted.PARTITION_BOOT)
144
print(f" Boot flag: {boot_flag}")
145
146
except parted.PartitionException as e:
147
print(f" Partition error: {e}")
148
149
except parted.DiskException as e:
150
print(f"Disk error: {e}")
151
except parted.DiskLabelException as e:
152
print(f"Disk label error: {e}")
153
154
except parted.DeviceException as e:
155
print(f"Device error: {e}")
156
except parted.IOException as e:
157
print(f"I/O error: {e}")
158
except Exception as e:
159
print(f"Unexpected error: {e}")
160
161
safe_disk_operations('/dev/sda')
162
```
163
164
### Partition Creation with Error Recovery
165
166
```python
167
import parted
168
169
def create_partition_with_recovery(device_path, size_gb):
170
"""Create partition with error recovery and fallback strategies."""
171
try:
172
device = parted.getDevice(device_path)
173
disk = parted.newDisk(device)
174
175
# Calculate partition geometry
176
size_sectors = int(size_gb * (1024**3) / device.sectorSize)
177
start_sector = 2048
178
179
try:
180
# Try optimal alignment first
181
constraint = device.getOptimalAlignedConstraint()
182
183
try:
184
geometry = parted.Geometry(device, start=start_sector, length=size_sectors)
185
186
# Check if geometry satisfies constraint
187
if constraint.isSolution(geometry):
188
print("Using requested geometry")
189
final_geometry = geometry
190
else:
191
print("Adjusting geometry to satisfy constraints")
192
final_geometry = constraint.solveNearest(geometry)
193
194
# Create partition
195
partition = parted.Partition(
196
disk=disk,
197
type=parted.PARTITION_NORMAL,
198
geometry=final_geometry
199
)
200
201
disk.addPartition(partition, constraint)
202
disk.commit()
203
204
print(f"Successfully created partition: {partition.path}")
205
return True
206
207
except parted.GeometryException as e:
208
print(f"Geometry error: {e}")
209
# Try with minimal constraint
210
print("Retrying with minimal alignment...")
211
constraint = device.getMinimalAlignedConstraint()
212
# ... retry logic here
213
214
except parted.ConstraintException as e:
215
print(f"Constraint error: {e}")
216
# Try with device-wide constraint
217
print("Retrying with device constraint...")
218
constraint = device.getConstraint()
219
# ... retry logic here
220
221
except parted.CreateException as e:
222
print(f"Creation failed: {e}")
223
return False
224
except parted.PartitionException as e:
225
print(f"Partition operation failed: {e}")
226
return False
227
except parted.DiskException as e:
228
print(f"Disk operation failed: {e}")
229
return False
230
except Exception as e:
231
print(f"Unexpected error: {e}")
232
return False
233
234
create_partition_with_recovery('/dev/sdb', 10) # 10GB partition
235
```
236
237
### Custom Exception Handler
238
239
```python
240
import parted
241
import sys
242
243
def interactive_exception_handler(exception_type, message, options):
244
"""Interactive exception handler for user decisions."""
245
246
# Map exception types to readable names
247
type_names = {
248
parted.EXCEPTION_TYPE_INFORMATION: "INFO",
249
parted.EXCEPTION_TYPE_WARNING: "WARNING",
250
parted.EXCEPTION_TYPE_ERROR: "ERROR",
251
parted.EXCEPTION_TYPE_FATAL: "FATAL",
252
parted.EXCEPTION_TYPE_BUG: "BUG",
253
parted.EXCEPTION_TYPE_NO_FEATURE: "NO_FEATURE"
254
}
255
256
type_name = type_names.get(exception_type, f"UNKNOWN({exception_type})")
257
print(f"\n{type_name}: {message}")
258
259
# Handle based on available options
260
if options == parted.EXCEPTION_OPT_OK_CANCEL:
261
response = input("Continue? (o)k/(c)ancel: ").lower()
262
return parted.EXCEPTION_RESOLVE_OK if response == 'o' else parted.EXCEPTION_RESOLVE_CANCEL
263
264
elif options == parted.EXCEPTION_OPT_YES_NO:
265
response = input("Continue? (y)es/(n)o: ").lower()
266
return parted.EXCEPTION_RESOLVE_YES if response == 'y' else parted.EXCEPTION_RESOLVE_NO
267
268
elif options == parted.EXCEPTION_OPT_YES_NO_CANCEL:
269
response = input("Action? (y)es/(n)o/(c)ancel: ").lower()
270
if response == 'y':
271
return parted.EXCEPTION_RESOLVE_YES
272
elif response == 'n':
273
return parted.EXCEPTION_RESOLVE_NO
274
else:
275
return parted.EXCEPTION_RESOLVE_CANCEL
276
277
elif options == parted.EXCEPTION_OPT_RETRY_CANCEL:
278
response = input("Action? (r)etry/(c)ancel: ").lower()
279
return parted.EXCEPTION_RESOLVE_RETRY if response == 'r' else parted.EXCEPTION_RESOLVE_CANCEL
280
281
elif options == parted.EXCEPTION_OPT_RETRY_IGNORE_CANCEL:
282
response = input("Action? (r)etry/(i)gnore/(c)ancel: ").lower()
283
if response == 'r':
284
return parted.EXCEPTION_RESOLVE_RETRY
285
elif response == 'i':
286
return parted.EXCEPTION_RESOLVE_IGNORE
287
else:
288
return parted.EXCEPTION_RESOLVE_CANCEL
289
290
elif options == parted.EXCEPTION_OPT_IGNORE_CANCEL:
291
response = input("Action? (i)gnore/(c)ancel: ").lower()
292
return parted.EXCEPTION_RESOLVE_IGNORE if response == 'i' else parted.EXCEPTION_RESOLVE_CANCEL
293
294
# Default to unhandled
295
return parted.EXCEPTION_RESOLVE_UNHANDLED
296
297
# Register the handler
298
parted.register_exn_handler(interactive_exception_handler)
299
300
# Use in operations
301
try:
302
device = parted.getDevice('/dev/sdb')
303
# ... perform operations that might trigger exceptions
304
print("Operations completed")
305
finally:
306
# Clean up handler
307
parted.clear_exn_handler()
308
```
309
310
### Logging Exception Handler
311
312
```python
313
import parted
314
import logging
315
import datetime
316
317
# Set up logging
318
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
319
logger = logging.getLogger('pyparted')
320
321
def logging_exception_handler(exception_type, message, options):
322
"""Exception handler that logs all exceptions."""
323
324
type_names = {
325
parted.EXCEPTION_TYPE_INFORMATION: "INFO",
326
parted.EXCEPTION_TYPE_WARNING: "WARNING",
327
parted.EXCEPTION_TYPE_ERROR: "ERROR",
328
parted.EXCEPTION_TYPE_FATAL: "FATAL",
329
parted.EXCEPTION_TYPE_BUG: "BUG",
330
parted.EXCEPTION_TYPE_NO_FEATURE: "NO_FEATURE"
331
}
332
333
type_name = type_names.get(exception_type, f"UNKNOWN({exception_type})")
334
335
# Log the exception
336
if exception_type == parted.EXCEPTION_TYPE_INFORMATION:
337
logger.info(f"libparted: {message}")
338
return parted.EXCEPTION_RESOLVE_OK
339
elif exception_type == parted.EXCEPTION_TYPE_WARNING:
340
logger.warning(f"libparted: {message}")
341
return parted.EXCEPTION_RESOLVE_OK
342
elif exception_type == parted.EXCEPTION_TYPE_ERROR:
343
logger.error(f"libparted: {message}")
344
# For non-interactive use, generally continue with "fix" or "ok"
345
return parted.EXCEPTION_RESOLVE_FIX
346
elif exception_type == parted.EXCEPTION_TYPE_FATAL:
347
logger.critical(f"libparted: {message}")
348
return parted.EXCEPTION_RESOLVE_CANCEL
349
else:
350
logger.error(f"libparted {type_name}: {message}")
351
return parted.EXCEPTION_RESOLVE_UNHANDLED
352
353
# Register logging handler
354
parted.register_exn_handler(logging_exception_handler)
355
356
def logged_disk_operations(device_path):
357
"""Perform disk operations with comprehensive logging."""
358
logger.info(f"Starting disk operations on {device_path}")
359
360
try:
361
device = parted.getDevice(device_path)
362
logger.info(f"Device opened: {device.model}")
363
364
disk = parted.newDisk(device)
365
logger.info(f"Disk read: {disk.type} with {len(disk.partitions)} partitions")
366
367
# Operations that might trigger libparted exceptions
368
if not disk.check():
369
logger.warning("Disk consistency check failed")
370
371
return True
372
373
except Exception as e:
374
logger.error(f"Operation failed: {e}")
375
return False
376
finally:
377
logger.info("Disk operations completed")
378
379
logged_disk_operations('/dev/sda')
380
```
381
382
### Exception Context Manager
383
384
```python
385
import parted
386
from contextlib import contextmanager
387
388
@contextmanager
389
def exception_handler_context(handler_func):
390
"""Context manager for temporary exception handler."""
391
parted.register_exn_handler(handler_func)
392
try:
393
yield
394
finally:
395
parted.clear_exn_handler()
396
397
def silent_handler(exception_type, message, options):
398
"""Silent handler that automatically resolves exceptions."""
399
if exception_type in [parted.EXCEPTION_TYPE_INFORMATION, parted.EXCEPTION_TYPE_WARNING]:
400
return parted.EXCEPTION_RESOLVE_OK
401
elif exception_type == parted.EXCEPTION_TYPE_ERROR:
402
return parted.EXCEPTION_RESOLVE_FIX
403
else:
404
return parted.EXCEPTION_RESOLVE_CANCEL
405
406
# Use context manager for specific operations
407
with exception_handler_context(silent_handler):
408
try:
409
device = parted.getDevice('/dev/sda')
410
disk = parted.newDisk(device)
411
# Perform operations with silent exception handling
412
print(f"Processed disk with {len(disk.partitions)} partitions")
413
except Exception as e:
414
print(f"Error: {e}")
415
416
print("Back to default exception handling")
417
```
418
419
### Exception Analysis and Reporting
420
421
```python
422
import parted
423
from collections import defaultdict
424
425
class ExceptionTracker:
426
"""Track and analyze exceptions during operations."""
427
428
def __init__(self):
429
self.exceptions = []
430
self.counts = defaultdict(int)
431
432
def handler(self, exception_type, message, options):
433
"""Exception handler that tracks exceptions."""
434
self.exceptions.append({
435
'type': exception_type,
436
'message': message,
437
'options': options,
438
'timestamp': parted.time.time()
439
})
440
self.counts[exception_type] += 1
441
442
# Provide reasonable default responses
443
if exception_type in [parted.EXCEPTION_TYPE_INFORMATION, parted.EXCEPTION_TYPE_WARNING]:
444
return parted.EXCEPTION_RESOLVE_OK
445
elif exception_type == parted.EXCEPTION_TYPE_ERROR:
446
return parted.EXCEPTION_RESOLVE_FIX
447
else:
448
return parted.EXCEPTION_RESOLVE_CANCEL
449
450
def report(self):
451
"""Generate exception report."""
452
if not self.exceptions:
453
print("No exceptions occurred")
454
return
455
456
type_names = {
457
parted.EXCEPTION_TYPE_INFORMATION: "INFO",
458
parted.EXCEPTION_TYPE_WARNING: "WARNING",
459
parted.EXCEPTION_TYPE_ERROR: "ERROR",
460
parted.EXCEPTION_TYPE_FATAL: "FATAL",
461
parted.EXCEPTION_TYPE_BUG: "BUG",
462
parted.EXCEPTION_TYPE_NO_FEATURE: "NO_FEATURE"
463
}
464
465
print(f"\nException Report: {len(self.exceptions)} total exceptions")
466
print("Summary by type:")
467
for exc_type, count in self.counts.items():
468
type_name = type_names.get(exc_type, f"UNKNOWN({exc_type})")
469
print(f" {type_name}: {count}")
470
471
print("\nDetailed exceptions:")
472
for i, exc in enumerate(self.exceptions, 1):
473
type_name = type_names.get(exc['type'], f"UNKNOWN({exc['type']})")
474
print(f" {i}. {type_name}: {exc['message']}")
475
476
# Use exception tracker
477
tracker = ExceptionTracker()
478
479
with exception_handler_context(tracker.handler):
480
try:
481
# Perform operations that might generate exceptions
482
devices = parted.getAllDevices()
483
for device in devices:
484
try:
485
disk = parted.newDisk(device)
486
disk.check()
487
except:
488
continue # Continue processing other devices
489
except Exception as e:
490
print(f"Error: {e}")
491
492
tracker.report()
493
```
494
495
## Exception Hierarchy
496
497
### Base Exceptions
498
- `PartedException` - Base class for all pyparted exceptions
499
- `Exception` - Python base exception class
500
501
### Specific Exception Categories
502
503
**Object Creation**:
504
- `CreateException` - Object creation failures
505
- `AlignmentException` - Alignment creation/operation failures
506
- `ConstraintException` - Constraint creation/solving failures
507
508
**Device/Disk Operations**:
509
- `DeviceException` - Device access/operation failures
510
- `DiskException` - Disk/partition table failures
511
- `DiskLabelException` - Disk label specific failures
512
- `IOException` - Low-level I/O failures
513
514
**Partition Operations**:
515
- `PartitionException` - Partition-specific failures
516
- `GeometryException` - Geometry calculation/validation failures
517
- `FileSystemException` - Filesystem operation failures
518
519
**Discovery/Identification**:
520
- `UnknownDeviceException` - Device identification failures
521
- `UnknownTypeException` - Type identification failures
522
523
## Best Practices
524
525
1. **Specific Exception Handling**: Catch specific exceptions rather than generic Exception
526
2. **Progressive Fallback**: Try optimal approaches first, fall back to simpler ones
527
3. **Resource Cleanup**: Use try/finally or context managers for cleanup
528
4. **User Feedback**: Provide meaningful error messages to users
529
5. **Logging**: Log exceptions for debugging and monitoring
530
6. **Exception Handlers**: Use custom handlers for automated or interactive scenarios