0
# System Control
1
2
Advanced functionality for operation introspection, cache management, and low-level system control for fine-tuning performance and behavior. These utilities provide control over libvips internals and enable advanced optimization strategies.
3
4
## Capabilities
5
6
### Operation System
7
8
Direct access to libvips operations and introspection capabilities for dynamic operation calling and documentation generation.
9
10
```python { .api }
11
class Operation:
12
"""Call libvips operations and provide introspection."""
13
14
@classmethod
15
def call(cls, operation_name: str, *args, **kwargs):
16
"""
17
Call any libvips operation by name.
18
19
Parameters:
20
- operation_name: str, name of the libvips operation
21
- *args: positional arguments for the operation
22
- **kwargs: keyword arguments for the operation
23
24
Returns:
25
Operation result (varies by operation)
26
"""
27
28
@classmethod
29
def generate_docstring(cls, operation_name: str) -> str:
30
"""
31
Generate Google-style docstring for operation.
32
33
Parameters:
34
- operation_name: str, operation name
35
36
Returns:
37
str, formatted docstring with parameters and description
38
"""
39
40
@classmethod
41
def generate_sphinx(cls, operation_name: str) -> str:
42
"""
43
Generate Sphinx-style docstring for operation.
44
45
Parameters:
46
- operation_name: str, operation name
47
48
Returns:
49
str, Sphinx-formatted docstring
50
"""
51
52
@classmethod
53
def generate_sphinx_all(cls) -> str:
54
"""
55
Generate Sphinx documentation for all operations.
56
57
Returns:
58
str, complete Sphinx documentation
59
"""
60
61
class Introspect:
62
"""Build and cache introspection data for operations."""
63
64
@classmethod
65
def get(cls, operation_name: str) -> 'Introspect':
66
"""
67
Get cached introspection data for operation.
68
69
Parameters:
70
- operation_name: str, operation name
71
72
Returns:
73
Introspect object with operation details
74
"""
75
76
# Properties
77
description: str # Operation description
78
flags: int # Operation flags
79
required_input: list # Required input parameters
80
optional_input: list # Optional input parameters
81
required_output: list # Required output parameters
82
optional_output: list # Optional output parameters
83
```
84
85
Example usage:
86
87
```python
88
# Direct operation calling
89
result = pyvips.Operation.call('add', image1, image2)
90
blurred = pyvips.Operation.call('gaussblur', image, 2.0)
91
92
# Advanced operation with all parameters
93
resized = pyvips.Operation.call('resize', image,
94
scale=0.5,
95
vscale=0.8,
96
kernel='lanczos3')
97
98
# Get operation documentation
99
doc = pyvips.Operation.generate_docstring('gaussblur')
100
print(doc)
101
102
# Introspect operation details
103
introspect = pyvips.Introspect.get('resize')
104
print(f"Description: {introspect.description}")
105
print(f"Required inputs: {introspect.required_input}")
106
print(f"Optional inputs: {introspect.optional_input}")
107
108
# List all available operations
109
import pyvips
110
operations = []
111
def collect_operations(name, operation):
112
operations.append(name)
113
pyvips.type_map(pyvips.type_from_name('VipsOperation'), collect_operations)
114
print(f"Available operations: {len(operations)}")
115
116
# Dynamic operation discovery
117
def call_operation_safely(op_name, *args, **kwargs):
118
"""Safely call operation with error handling."""
119
try:
120
introspect = pyvips.Introspect.get(op_name)
121
print(f"Calling {op_name}: {introspect.description}")
122
return pyvips.Operation.call(op_name, *args, **kwargs)
123
except pyvips.Error as e:
124
print(f"Operation {op_name} failed: {e}")
125
return None
126
127
# Use dynamic calling
128
result = call_operation_safely('thumbnail', image, 200)
129
```
130
131
### Cache Management
132
133
Control libvips operation cache for memory management and performance optimization.
134
135
```python { .api }
136
def cache_set_max(mx: int) -> None:
137
"""
138
Set maximum number of operations in cache.
139
140
Parameters:
141
- mx: int, maximum cache entries (0 = unlimited)
142
"""
143
144
def cache_set_max_mem(mx: int) -> None:
145
"""
146
Set maximum cache memory usage.
147
148
Parameters:
149
- mx: int, maximum memory in bytes (0 = unlimited)
150
"""
151
152
def cache_set_max_files(mx: int) -> None:
153
"""
154
Set maximum open files in cache.
155
156
Parameters:
157
- mx: int, maximum open files (0 = unlimited)
158
"""
159
160
def cache_set_trace(trace: bool) -> None:
161
"""
162
Enable/disable cache operation tracing.
163
164
Parameters:
165
- trace: bool, enable tracing for debugging
166
"""
167
168
def cache_get_max() -> int:
169
"""Get maximum cache entries setting."""
170
171
def cache_get_size() -> int:
172
"""Get current cache size (number of entries)."""
173
174
def cache_get_max_mem() -> int:
175
"""Get maximum cache memory setting."""
176
177
def cache_get_max_files() -> int:
178
"""Get maximum open files setting."""
179
```
180
181
Example usage:
182
183
```python
184
# Cache configuration for memory-constrained environments
185
pyvips.cache_set_max_mem(100 * 1024 * 1024) # 100MB limit
186
pyvips.cache_set_max_files(50) # Limit open files
187
pyvips.cache_set_max(200) # Limit cache entries
188
189
# Cache configuration for high-performance environments
190
pyvips.cache_set_max_mem(1 * 1024 * 1024 * 1024) # 1GB limit
191
pyvips.cache_set_max_files(1000) # More open files
192
pyvips.cache_set_max(0) # Unlimited entries
193
194
# Monitor cache usage
195
def print_cache_stats():
196
print(f"Cache size: {pyvips.cache_get_size()}")
197
print(f"Max entries: {pyvips.cache_get_max()}")
198
print(f"Max memory: {pyvips.cache_get_max_mem()} bytes")
199
print(f"Max files: {pyvips.cache_get_max_files()}")
200
201
print_cache_stats()
202
203
# Enable cache tracing for debugging
204
pyvips.cache_set_trace(True)
205
image = pyvips.Image.new_from_file('test.jpg')
206
resized = image.resize(0.5) # Will show cache operations
207
pyvips.cache_set_trace(False)
208
209
# Adaptive cache management
210
def setup_cache_for_batch_processing(image_count, avg_image_size_mb):
211
"""Configure cache for batch processing workload."""
212
213
# Estimate memory needs
214
total_mem_mb = image_count * avg_image_size_mb * 2 # Factor for operations
215
216
# Set conservative limits
217
pyvips.cache_set_max_mem(min(total_mem_mb * 1024 * 1024, 512 * 1024 * 1024))
218
pyvips.cache_set_max_files(min(image_count * 2, 200))
219
pyvips.cache_set_max(min(image_count * 5, 500))
220
221
print(f"Cache configured for {image_count} images")
222
print_cache_stats()
223
224
# Dynamic cache adjustment
225
def monitor_and_adjust_cache():
226
"""Monitor cache performance and adjust settings."""
227
import psutil
228
229
# Get system memory info
230
memory = psutil.virtual_memory()
231
available_mb = memory.available // (1024 * 1024)
232
233
# Adjust cache based on available memory
234
if available_mb > 2048: # > 2GB available
235
pyvips.cache_set_max_mem(512 * 1024 * 1024) # Use 512MB
236
elif available_mb > 1024: # > 1GB available
237
pyvips.cache_set_max_mem(256 * 1024 * 1024) # Use 256MB
238
else: # Low memory
239
pyvips.cache_set_max_mem(64 * 1024 * 1024) # Use 64MB
240
241
print(f"Adjusted cache for {available_mb}MB available memory")
242
```
243
244
### Version Information
245
246
Access libvips version information for compatibility checking and feature detection.
247
248
```python { .api }
249
def version(flag: int) -> int:
250
"""
251
Get libvips version information.
252
253
Parameters:
254
- flag: int, version component (0=major, 1=minor, 2=micro)
255
256
Returns:
257
int, version number component
258
"""
259
260
def at_least_libvips(x: int, y: int) -> bool:
261
"""
262
Check if libvips version is at least x.y.
263
264
Parameters:
265
- x: int, major version
266
- y: int, minor version
267
268
Returns:
269
bool, True if version >= x.y
270
"""
271
```
272
273
Example usage:
274
275
```python
276
# Get version information
277
major = pyvips.version(0)
278
minor = pyvips.version(1)
279
micro = pyvips.version(2)
280
print(f"libvips version: {major}.{minor}.{micro}")
281
282
# Check for specific features
283
if pyvips.at_least_libvips(8, 13):
284
print("TargetCustom.on_end() is available")
285
# Use newer features
286
else:
287
print("Using legacy TargetCustom.on_finish()")
288
# Use older API
289
290
# Feature detection
291
def has_feature(feature_name, min_major, min_minor):
292
"""Check if a feature is available in current libvips version."""
293
return pyvips.at_least_libvips(min_major, min_minor)
294
295
# Check various features
296
features = {
297
'custom_sources': (8, 9),
298
'target_custom_end': (8, 13),
299
'heif_support': (8, 8),
300
'webp_animation': (8, 9)
301
}
302
303
for feature, (maj, min) in features.items():
304
available = has_feature(feature, maj, min)
305
print(f"{feature}: {'✓' if available else '✗'}")
306
307
# Version-dependent operation calling
308
def safe_operation_call(op_name, required_version, *args, **kwargs):
309
"""Call operation only if libvips version supports it."""
310
maj, min = required_version
311
if pyvips.at_least_libvips(maj, min):
312
return pyvips.Operation.call(op_name, *args, **kwargs)
313
else:
314
raise pyvips.Error(f"Operation {op_name} requires libvips >= {maj}.{min}")
315
316
# Use version checking
317
try:
318
result = safe_operation_call('heifload', (8, 8), 'image.heic')
319
print("HEIF loading successful")
320
except pyvips.Error as e:
321
print(f"HEIF not supported: {e}")
322
```
323
324
### Security Controls (libvips >= 8.13)
325
326
Security features for controlling potentially dangerous operations in untrusted environments.
327
328
```python { .api }
329
def block_untrusted_set(state: bool) -> None:
330
"""
331
Set global block state for untrusted operations.
332
333
Parameters:
334
- state: bool, True to block untrusted operations
335
"""
336
337
def operation_block_set(name: str, state: bool) -> None:
338
"""
339
Set block state for specific operation.
340
341
Parameters:
342
- name: str, operation name to block/unblock
343
- state: bool, True to block operation
344
"""
345
```
346
347
Example usage:
348
349
```python
350
# Security setup for web service
351
if pyvips.at_least_libvips(8, 13):
352
# Block potentially dangerous operations
353
pyvips.block_untrusted_set(True)
354
355
# Block specific operations that might be security risks
356
dangerous_ops = [
357
'system', # System command execution
358
'pdfload', # PDF might contain malicious content
359
'svgload', # SVG can contain scripts
360
'magickload' # ImageMagick has security history
361
]
362
363
for op in dangerous_ops:
364
try:
365
pyvips.operation_block_set(op, True)
366
print(f"Blocked operation: {op}")
367
except:
368
print(f"Could not block {op} (might not exist)")
369
370
# Safe image processing for user uploads
371
def process_user_upload(image_data, max_size_mb=10):
372
"""Safely process user-uploaded images."""
373
374
# Size check
375
if len(image_data) > max_size_mb * 1024 * 1024:
376
raise ValueError(f"Image too large: {len(image_data)} bytes")
377
378
# Enable security restrictions
379
if pyvips.at_least_libvips(8, 13):
380
pyvips.block_untrusted_set(True)
381
382
try:
383
# Load with restrictions
384
image = pyvips.Image.new_from_buffer(image_data, '')
385
386
# Limit output size
387
if image.width > 4096 or image.height > 4096:
388
image = image.thumbnail_image(4096)
389
390
# Safe processing only
391
result = (image
392
.colourspace('srgb')
393
.resize(0.8)
394
.sharpen())
395
396
return result.write_to_buffer('.jpg', Q=85, strip=True)
397
398
except pyvips.Error as e:
399
raise ValueError(f"Image processing failed: {e}")
400
401
finally:
402
# Reset security state if needed
403
if pyvips.at_least_libvips(8, 13):
404
pyvips.block_untrusted_set(False)
405
```
406
407
### System Management
408
409
Low-level system control and resource management functions.
410
411
```python { .api }
412
def leak_set(leak: bool) -> None:
413
"""
414
Enable/disable libvips leak checking.
415
416
Parameters:
417
- leak: bool, enable leak detection for debugging
418
"""
419
420
def shutdown() -> None:
421
"""
422
Shut down libvips system.
423
Call before program exit to clean up resources.
424
"""
425
```
426
427
Example usage:
428
429
```python
430
# Development/debugging setup
431
import atexit
432
433
def setup_debug_environment():
434
"""Configure libvips for debugging."""
435
# Enable leak checking
436
pyvips.leak_set(True)
437
438
# Enable cache tracing
439
pyvips.cache_set_trace(True)
440
441
# Register cleanup
442
atexit.register(pyvips.shutdown)
443
444
print("Debug environment configured")
445
446
# Production setup
447
def setup_production_environment():
448
"""Configure libvips for production."""
449
# Disable leak checking for performance
450
pyvips.leak_set(False)
451
452
# Optimize cache for server workload
453
pyvips.cache_set_max_mem(256 * 1024 * 1024) # 256MB
454
pyvips.cache_set_max_files(100)
455
pyvips.cache_set_max(1000)
456
457
# Security setup
458
if pyvips.at_least_libvips(8, 13):
459
pyvips.block_untrusted_set(True)
460
461
# Register cleanup
462
atexit.register(pyvips.shutdown)
463
464
print("Production environment configured")
465
466
# Application lifecycle management
467
class PyVipsManager:
468
"""Manage PyVips lifecycle and configuration."""
469
470
def __init__(self, environment='production'):
471
self.environment = environment
472
self.setup()
473
474
def setup(self):
475
"""Setup based on environment."""
476
if self.environment == 'development':
477
setup_debug_environment()
478
else:
479
setup_production_environment()
480
481
def get_system_info(self):
482
"""Get system and version information."""
483
return {
484
'pyvips_version': pyvips.__version__,
485
'libvips_version': f"{pyvips.version(0)}.{pyvips.version(1)}.{pyvips.version(2)}",
486
'api_mode': pyvips.API_mode,
487
'cache_size': pyvips.cache_get_size(),
488
'cache_max': pyvips.cache_get_max(),
489
'cache_max_mem': pyvips.cache_get_max_mem(),
490
'cache_max_files': pyvips.cache_get_max_files()
491
}
492
493
def cleanup(self):
494
"""Clean shutdown."""
495
print("Shutting down PyVips...")
496
pyvips.shutdown()
497
498
# Use lifecycle manager
499
manager = PyVipsManager('production')
500
print("System info:", manager.get_system_info())
501
502
# Register cleanup
503
import atexit
504
atexit.register(manager.cleanup)
505
```
506
507
## Performance Monitoring
508
509
```python
510
import time
511
import psutil
512
513
class PerformanceMonitor:
514
"""Monitor PyVips performance and resource usage."""
515
516
def __init__(self):
517
self.start_time = time.time()
518
self.initial_memory = psutil.Process().memory_info().rss
519
520
def log_stats(self, operation):
521
"""Log performance statistics."""
522
current_time = time.time()
523
current_memory = psutil.Process().memory_info().rss
524
525
cache_size = pyvips.cache_get_size()
526
527
print(f"Operation: {operation}")
528
print(f" Time: {current_time - self.start_time:.2f}s")
529
print(f" Memory: {(current_memory - self.initial_memory) / 1024 / 1024:.1f}MB")
530
print(f" Cache size: {cache_size} entries")
531
532
self.start_time = current_time
533
534
def optimize_for_workload(self, workload_type):
535
"""Optimize cache settings for specific workload."""
536
if workload_type == 'batch':
537
pyvips.cache_set_max(2000)
538
pyvips.cache_set_max_mem(512 * 1024 * 1024)
539
elif workload_type == 'interactive':
540
pyvips.cache_set_max(100)
541
pyvips.cache_set_max_mem(128 * 1024 * 1024)
542
elif workload_type == 'memory_constrained':
543
pyvips.cache_set_max(50)
544
pyvips.cache_set_max_mem(64 * 1024 * 1024)
545
546
# Use performance monitoring
547
monitor = PerformanceMonitor()
548
monitor.optimize_for_workload('batch')
549
550
image = pyvips.Image.new_from_file('large.tiff')
551
monitor.log_stats('load')
552
553
processed = image.resize(0.5).sharpen()
554
monitor.log_stats('process')
555
556
processed.write_to_file('output.jpg')
557
monitor.log_stats('save')
558
```