or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

configuration.mdcore-serialization.mddiagnostic-tools.mdindex.mdpickler-classes.mdsession-management.mdsource-analysis.mdtemp-operations.mdtype-registry.md

configuration.mddocs/

0

# Configuration and Settings

1

2

dill provides global configuration options and settings that control serialization behavior, protocol selection, and various operational modes for optimal performance and compatibility.

3

4

## Global Settings

5

6

### Settings Dictionary

7

8

```python { .api }

9

# Global settings dictionary

10

settings = {

11

'protocol': DEFAULT_PROTOCOL, # int: Default pickle protocol version

12

'byref': False, # bool: Pickle by reference when possible

13

'fmode': 0, # int: File mode setting (0=HANDLE_FMODE, 1=CONTENTS_FMODE, 2=FILE_FMODE)

14

'recurse': False, # bool: Recursively pickle nested objects

15

'ignore': False # bool: Ignore certain errors during serialization

16

}

17

```

18

19

### Protocol Constants

20

21

```python { .api }

22

DEFAULT_PROTOCOL = 3 # Default pickle protocol version

23

HIGHEST_PROTOCOL = 5 # Highest supported pickle protocol version

24

25

# File mode constants

26

HANDLE_FMODE = 0 # Preserve file handles during serialization

27

CONTENTS_FMODE = 1 # Save file contents instead of handles

28

FILE_FMODE = 2 # Save file metadata and paths

29

```

30

31

### Extension Control

32

33

```python { .api }

34

def extend(use_dill=True):

35

"""

36

Add or remove dill types to/from the pickle registry.

37

38

Controls whether dill's extended types are available in the standard

39

pickle module's dispatch table for backward compatibility.

40

41

Parameters:

42

- use_dill: bool, if True extend dispatch table with dill types,

43

if False revert to standard pickle types only

44

45

Returns:

46

None

47

"""

48

```

49

50

## Usage Examples

51

52

### Basic Configuration

53

54

```python

55

import dill

56

57

# Check current settings

58

print("Current settings:")

59

for key, value in dill.settings.items():

60

print(f" {key}: {value}")

61

62

# Modify settings

63

original_protocol = dill.settings['protocol']

64

dill.settings['protocol'] = dill.HIGHEST_PROTOCOL

65

dill.settings['byref'] = True

66

67

print(f"\\nChanged protocol from {original_protocol} to {dill.settings['protocol']}")

68

print(f"Enabled byref: {dill.settings['byref']}")

69

70

# Test with new settings

71

def test_function():

72

return "Hello with new settings!"

73

74

serialized = dill.dumps(test_function)

75

restored = dill.loads(serialized)

76

print(f"Function result: {restored()}")

77

78

# Restore original settings

79

dill.settings['protocol'] = original_protocol

80

dill.settings['byref'] = False

81

```

82

83

### Protocol Selection and Performance

84

85

```python

86

import dill

87

import time

88

89

def benchmark_protocols(obj, protocols=None):

90

"""Benchmark different pickle protocols."""

91

if protocols is None:

92

protocols = [0, 1, 2, 3, 4, dill.HIGHEST_PROTOCOL]

93

94

results = {}

95

96

for protocol in protocols:

97

try:

98

# Set protocol

99

original_protocol = dill.settings['protocol']

100

dill.settings['protocol'] = protocol

101

102

# Time serialization

103

start_time = time.time()

104

serialized = dill.dumps(obj)

105

serialize_time = time.time() - start_time

106

107

# Time deserialization

108

start_time = time.time()

109

dill.loads(serialized)

110

deserialize_time = time.time() - start_time

111

112

results[protocol] = {

113

'serialize_time': serialize_time,

114

'deserialize_time': deserialize_time,

115

'size': len(serialized),

116

'total_time': serialize_time + deserialize_time

117

}

118

119

# Restore original protocol

120

dill.settings['protocol'] = original_protocol

121

122

except Exception as e:

123

results[protocol] = {'error': str(e)}

124

125

return results

126

127

# Test with complex object

128

complex_obj = {

129

'functions': [lambda x: x**i for i in range(5)],

130

'data': list(range(1000)),

131

'nested': {'level1': {'level2': [i*j for i in range(10) for j in range(10)]}}

132

}

133

134

protocol_results = benchmark_protocols(complex_obj)

135

136

print("Protocol Performance Comparison:")

137

print("-" * 50)

138

for protocol, result in protocol_results.items():

139

if 'error' in result:

140

print(f"Protocol {protocol}: ERROR - {result['error']}")

141

else:

142

print(f"Protocol {protocol}:")

143

print(f" Serialize: {result['serialize_time']:.4f}s")

144

print(f" Deserialize: {result['deserialize_time']:.4f}s")

145

print(f" Size: {result['size']:,} bytes")

146

print(f" Total: {result['total_time']:.4f}s")

147

```

148

149

### File Mode Configuration

150

151

```python

152

import dill

153

import tempfile

154

import io

155

156

def demonstrate_file_modes():

157

"""Demonstrate different file mode behaviors."""

158

159

# Create object with file handle

160

temp_file = tempfile.NamedTemporaryFile(mode='w+', delete=False)

161

temp_file.write("Test data for file mode demonstration")

162

temp_file.seek(0)

163

164

obj_with_file = {

165

'file_handle': temp_file,

166

'file_path': temp_file.name,

167

'data': [1, 2, 3, 4, 5]

168

}

169

170

# Test different file modes

171

modes = {

172

dill.HANDLE_FMODE: "HANDLE_FMODE (preserve handles)",

173

dill.CONTENTS_FMODE: "CONTENTS_FMODE (save contents)",

174

dill.FILE_FMODE: "FILE_FMODE (save metadata)"

175

}

176

177

for fmode, description in modes.items():

178

print(f"\\nTesting {description}:")

179

print("-" * 40)

180

181

try:

182

# Set file mode

183

original_fmode = dill.settings['fmode']

184

dill.settings['fmode'] = fmode

185

186

# Serialize

187

serialized = dill.dumps(obj_with_file)

188

print(f"✓ Serialization successful ({len(serialized)} bytes)")

189

190

# Deserialize

191

restored = dill.loads(serialized)

192

print(f"✓ Deserialization successful")

193

194

# Test restored file behavior

195

if 'file_handle' in restored:

196

file_obj = restored['file_handle']

197

if hasattr(file_obj, 'read'):

198

try:

199

content = file_obj.read()

200

print(f"✓ File content: {repr(content[:50])}")

201

except:

202

print("✗ File handle not functional")

203

else:

204

print("○ File handle replaced with alternative representation")

205

206

# Restore original setting

207

dill.settings['fmode'] = original_fmode

208

209

except Exception as e:

210

print(f"✗ Failed: {e}")

211

212

# Cleanup

213

temp_file.close()

214

import os

215

os.unlink(temp_file.name)

216

217

demonstrate_file_modes()

218

```

219

220

### Reference vs Value Serialization

221

222

```python

223

import dill

224

225

def demonstrate_byref_setting():

226

"""Demonstrate byref setting effects."""

227

228

# Create shared object

229

shared_list = [1, 2, 3, 4, 5]

230

231

# Create objects that reference the shared list

232

obj1 = {'data': shared_list, 'name': 'object1'}

233

obj2 = {'data': shared_list, 'name': 'object2'}

234

container = {'obj1': obj1, 'obj2': obj2, 'shared': shared_list}

235

236

# Test with byref=False (default)

237

print("Testing with byref=False (value serialization):")

238

dill.settings['byref'] = False

239

240

serialized_value = dill.dumps(container)

241

restored_value = dill.loads(serialized_value)

242

243

# Modify shared list in restored object

244

restored_value['shared'].append(999)

245

246

print(f" Original obj1 data: {container['obj1']['data']}")

247

print(f" Restored obj1 data: {restored_value['obj1']['data']}")

248

print(f" Restored obj2 data: {restored_value['obj2']['data']}")

249

print(f" Objects share data in restored: {restored_value['obj1']['data'] is restored_value['obj2']['data']}")

250

251

# Test with byref=True

252

print("\\nTesting with byref=True (reference serialization):")

253

dill.settings['byref'] = True

254

255

serialized_ref = dill.dumps(container)

256

restored_ref = dill.loads(serialized_ref)

257

258

# Modify shared list in restored object

259

restored_ref['shared'].append(888)

260

261

print(f" Restored obj1 data: {restored_ref['obj1']['data']}")

262

print(f" Restored obj2 data: {restored_ref['obj2']['data']}")

263

print(f" Objects share data in restored: {restored_ref['obj1']['data'] is restored_ref['obj2']['data']}")

264

265

print(f"\\nSerialized sizes:")

266

print(f" Value mode: {len(serialized_value)} bytes")

267

print(f" Reference mode: {len(serialized_ref)} bytes")

268

269

# Restore default

270

dill.settings['byref'] = False

271

272

demonstrate_byref_setting()

273

```

274

275

### Recursive Serialization Control

276

277

```python

278

import dill

279

280

def demonstrate_recursive_setting():

281

"""Demonstrate recursive serialization setting."""

282

283

# Create nested structure with functions

284

def outer_function(x):

285

def inner_function(y):

286

def innermost_function(z):

287

return x + y + z

288

return innermost_function

289

return inner_function

290

291

nested_func = outer_function(10)

292

deeply_nested = nested_func(20)

293

294

test_obj = {

295

'outer': outer_function,

296

'nested': nested_func,

297

'deep': deeply_nested,

298

'data': {'level1': {'level2': {'level3': [1, 2, 3]}}}

299

}

300

301

# Test with recurse=False (default)

302

print("Testing with recurse=False:")

303

dill.settings['recurse'] = False

304

305

try:

306

serialized_no_recurse = dill.dumps(test_obj)

307

restored_no_recurse = dill.loads(serialized_no_recurse)

308

309

# Test functionality

310

result = restored_no_recurse['deep'](30)

311

print(f" ✓ Serialization successful, result: {result}")

312

print(f" Size: {len(serialized_no_recurse)} bytes")

313

except Exception as e:

314

print(f" ✗ Failed: {e}")

315

316

# Test with recurse=True

317

print("\\nTesting with recurse=True:")

318

dill.settings['recurse'] = True

319

320

try:

321

serialized_recurse = dill.dumps(test_obj)

322

restored_recurse = dill.loads(serialized_recurse)

323

324

# Test functionality

325

result = restored_recurse['deep'](30)

326

print(f" ✓ Serialization successful, result: {result}")

327

print(f" Size: {len(serialized_recurse)} bytes")

328

except Exception as e:

329

print(f" ✗ Failed: {e}")

330

331

# Restore default

332

dill.settings['recurse'] = False

333

334

demonstrate_recursive_setting()

335

```

336

337

## Advanced Configuration Management

338

339

### Configuration Context Manager

340

341

```python

342

import dill

343

from contextlib import contextmanager

344

345

@contextmanager

346

def dill_config(**settings):

347

"""Context manager for temporary dill configuration."""

348

# Save original settings

349

original = dill.settings.copy()

350

351

# Apply new settings

352

dill.settings.update(settings)

353

354

try:

355

yield dill.settings

356

finally:

357

# Restore original settings

358

dill.settings.clear()

359

dill.settings.update(original)

360

361

# Usage examples

362

def test_function():

363

return "Test result"

364

365

# Temporary high-performance configuration

366

with dill_config(protocol=dill.HIGHEST_PROTOCOL, byref=True):

367

print(f"Using protocol: {dill.settings['protocol']}")

368

serialized = dill.dumps(test_function)

369

print(f"Serialized size: {len(serialized)} bytes")

370

371

# Back to default settings

372

print(f"Back to protocol: {dill.settings['protocol']}")

373

374

# Temporary memory-efficient configuration

375

with dill_config(fmode=dill.CONTENTS_FMODE, recurse=True):

376

complex_obj = {'data': [1, 2, 3], 'func': lambda x: x*2}

377

serialized = dill.dumps(complex_obj)

378

restored = dill.loads(serialized)

379

print(f"Function result: {restored['func'](5)}")

380

```

381

382

### Configuration Profiles

383

384

```python

385

import dill

386

387

class DillProfile:

388

"""Predefined configuration profiles for different use cases."""

389

390

# Performance-optimized profile

391

PERFORMANCE = {

392

'protocol': dill.HIGHEST_PROTOCOL,

393

'byref': False,

394

'fmode': dill.HANDLE_FMODE,

395

'recurse': False,

396

'ignore': False

397

}

398

399

# Size-optimized profile

400

COMPACT = {

401

'protocol': dill.HIGHEST_PROTOCOL,

402

'byref': True,

403

'fmode': dill.CONTENTS_FMODE,

404

'recurse': True,

405

'ignore': False

406

}

407

408

# Compatibility profile

409

COMPATIBLE = {

410

'protocol': 2, # Widely supported protocol

411

'byref': False,

412

'fmode': dill.CONTENTS_FMODE,

413

'recurse': False,

414

'ignore': True

415

}

416

417

# Debug profile

418

DEBUG = {

419

'protocol': 0, # Human-readable protocol

420

'byref': False,

421

'fmode': dill.CONTENTS_FMODE,

422

'recurse': True,

423

'ignore': False

424

}

425

426

class ConfigManager:

427

"""Configuration management utility."""

428

429

def __init__(self):

430

self.saved_configs = {}

431

self.current_profile = None

432

433

def apply_profile(self, profile_name):

434

"""Apply a predefined profile."""

435

profiles = {

436

'performance': DillProfile.PERFORMANCE,

437

'compact': DillProfile.COMPACT,

438

'compatible': DillProfile.COMPATIBLE,

439

'debug': DillProfile.DEBUG

440

}

441

442

if profile_name in profiles:

443

# Save current config

444

self.save_config('pre_profile')

445

446

# Apply profile

447

dill.settings.update(profiles[profile_name])

448

self.current_profile = profile_name

449

450

print(f"Applied {profile_name} profile:")

451

for key, value in profiles[profile_name].items():

452

print(f" {key}: {value}")

453

else:

454

print(f"Unknown profile: {profile_name}")

455

456

def save_config(self, name):

457

"""Save current configuration."""

458

self.saved_configs[name] = dill.settings.copy()

459

print(f"Saved configuration as '{name}'")

460

461

def restore_config(self, name):

462

"""Restore saved configuration."""

463

if name in self.saved_configs:

464

dill.settings.clear()

465

dill.settings.update(self.saved_configs[name])

466

self.current_profile = None

467

print(f"Restored configuration '{name}'")

468

else:

469

print(f"No saved configuration named '{name}'")

470

471

def list_configs(self):

472

"""List saved configurations."""

473

print("Saved configurations:")

474

for name in self.saved_configs:

475

print(f" - {name}")

476

477

def show_current_config(self):

478

"""Show current configuration."""

479

print("Current configuration:")

480

for key, value in dill.settings.items():

481

print(f" {key}: {value}")

482

if self.current_profile:

483

print(f"Profile: {self.current_profile}")

484

485

# Usage example

486

config_manager = ConfigManager()

487

488

# Test different profiles

489

test_obj = {

490

'function': lambda x: x**2,

491

'data': list(range(100)),

492

'nested': {'level1': {'level2': 'deep_value'}}

493

}

494

495

profiles_to_test = ['performance', 'compact', 'compatible', 'debug']

496

497

for profile in profiles_to_test:

498

print(f"\\n{'='*50}")

499

print(f"Testing {profile.upper()} profile")

500

print('='*50)

501

502

config_manager.apply_profile(profile)

503

504

try:

505

serialized = dill.dumps(test_obj)

506

restored = dill.loads(serialized)

507

508

print(f"✓ Serialization successful")

509

print(f" Size: {len(serialized):,} bytes")

510

print(f" Function test: {restored['function'](5)}")

511

512

except Exception as e:

513

print(f"✗ Failed: {e}")

514

515

# Restore original configuration

516

config_manager.restore_config('pre_profile')

517

```

518

519

### Environment-Specific Configuration

520

521

```python

522

import dill

523

import os

524

import platform

525

import sys

526

527

class EnvironmentConfig:

528

"""Automatically configure dill based on environment."""

529

530

@staticmethod

531

def auto_configure():

532

"""Automatically configure based on environment."""

533

config = {}

534

535

# Python version considerations

536

if sys.version_info >= (3, 8):

537

config['protocol'] = dill.HIGHEST_PROTOCOL

538

else:

539

config['protocol'] = 3 # Safe for older versions

540

541

# Platform considerations

542

if platform.system() == 'Windows':

543

config['fmode'] = dill.CONTENTS_FMODE # Better Windows compatibility

544

else:

545

config['fmode'] = dill.HANDLE_FMODE

546

547

# Memory considerations

548

import psutil

549

available_memory = psutil.virtual_memory().available

550

if available_memory < 1024**3: # Less than 1GB

551

config['byref'] = True # Save memory

552

config['recurse'] = False

553

else:

554

config['byref'] = False

555

config['recurse'] = True

556

557

# Development vs production

558

if os.environ.get('DILL_DEBUG'):

559

config['protocol'] = 0 # Human-readable

560

config['ignore'] = False # Strict error handling

561

elif os.environ.get('DILL_PRODUCTION'):

562

config['ignore'] = True # Lenient error handling

563

564

# Apply configuration

565

dill.settings.update(config)

566

567

print("Auto-configured dill based on environment:")

568

for key, value in config.items():

569

print(f" {key}: {value}")

570

571

return config

572

573

@staticmethod

574

def validate_config():

575

"""Validate current configuration."""

576

issues = []

577

578

# Check protocol compatibility

579

if dill.settings['protocol'] > 4 and sys.version_info < (3, 8):

580

issues.append("Protocol 5 requires Python 3.8+")

581

582

# Check memory usage with byref setting

583

if not dill.settings['byref'] and dill.settings['recurse']:

584

issues.append("High memory usage: recurse=True with byref=False")

585

586

# Check file mode compatibility

587

if dill.settings['fmode'] == dill.HANDLE_FMODE and platform.system() == 'Windows':

588

issues.append("HANDLE_FMODE may have issues on Windows")

589

590

if issues:

591

print("Configuration issues found:")

592

for issue in issues:

593

print(f" ⚠ {issue}")

594

else:

595

print("✓ Configuration validation passed")

596

597

return len(issues) == 0

598

599

# Example usage

600

print("Current system information:")

601

print(f" Python: {sys.version}")

602

print(f" Platform: {platform.system()}")

603

print(f" Memory: {psutil.virtual_memory().total / (1024**3):.1f}GB")

604

605

# Auto-configure

606

env_config = EnvironmentConfig()

607

env_config.auto_configure()

608

609

# Validate configuration

610

env_config.validate_config()

611

612

# Test with auto-configuration

613

test_function = lambda x: x * 2 + 1

614

serialized = dill.dumps(test_function)

615

restored = dill.loads(serialized)

616

print(f"\\nTest result: {restored(10)}")

617

print(f"Serialized size: {len(serialized)} bytes")

618

```

619

620

## Best Practices

621

622

### Configuration Management Guidelines

623

624

1. **Profile Usage**: Use predefined profiles for common scenarios

625

2. **Context Managers**: Use context managers for temporary configuration changes

626

3. **Environment Awareness**: Configure based on deployment environment

627

4. **Performance Testing**: Benchmark different configurations for your use case

628

5. **Documentation**: Document configuration choices and their rationale

629

630

### Performance Considerations

631

632

1. **Protocol Selection**: Higher protocols generally offer better performance

633

2. **Memory vs Speed**: `byref=True` saves memory but may slow deserialization

634

3. **File Mode Impact**: Choose file mode based on your file handling needs

635

4. **Recursive Overhead**: Enable recursion only when necessary for complex objects