or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

communication.mdcontext-config.mdindex.mdpools.mdprocess-management.mdshared-objects.mdsynchronization.md

context-config.mddocs/

0

# Context and Configuration

1

2

Context management and configuration options for different process start methods and serialization behavior. Allows fine-grained control over process creation and object serialization in multiprocess applications.

3

4

## Capabilities

5

6

### Context Management

7

8

Functions for managing different process start methods and contexts.

9

10

```python { .api }

11

def get_context(method=None):

12

"""

13

Get a context for a specific start method.

14

15

Args:

16

method: start method ('fork', 'spawn', 'forkserver', or None)

17

None returns the current default context

18

19

Returns:

20

BaseContext: context object for the specified method

21

22

Raises:

23

ValueError: if method is not available on the platform

24

"""

25

26

def set_start_method(method, force=False):

27

"""

28

Set the start method for creating processes.

29

30

Args:

31

method: start method ('fork', 'spawn', 'forkserver')

32

force: if True, allow changing after context has been used

33

34

Raises:

35

RuntimeError: if context has already been set and force=False

36

ValueError: if method is not available

37

"""

38

39

def get_start_method(allow_none=False):

40

"""

41

Get the current start method.

42

43

Args:

44

allow_none: if True, return None if no method has been set

45

46

Returns:

47

str: current start method name

48

"""

49

50

def get_all_start_methods():

51

"""

52

Get all available start methods for the platform.

53

54

Returns:

55

list[str]: list of available start methods, default first

56

"""

57

```

58

59

### Context Objects

60

61

Different context types for specific start methods.

62

63

```python { .api }

64

class BaseContext:

65

"""

66

Base context class providing multiprocess functionality.

67

"""

68

# All the standard multiprocess functions are available on context objects

69

def Process(self, target=None, name=None, args=(), kwargs={}, daemon=None):

70

"""Create a Process using this context."""

71

72

def Pool(self, processes=None, initializer=None, initargs=(),

73

maxtasksperchild=None):

74

"""Create a Pool using this context."""

75

76

def Queue(self, maxsize=0):

77

"""Create a Queue using this context."""

78

79

def Lock(self):

80

"""Create a Lock using this context."""

81

82

def Manager(self):

83

"""Create a Manager using this context."""

84

85

# ... all other multiprocess functions available

86

```

87

88

### Process Configuration

89

90

Functions for configuring process behavior and execution environment.

91

92

```python { .api }

93

def set_executable(executable):

94

"""

95

Set the path to Python executable for spawned processes.

96

97

Useful when embedding Python or using custom Python installations.

98

Only affects 'spawn' start method.

99

100

Args:

101

executable: path to Python executable

102

"""

103

104

def set_forkserver_preload(module_names):

105

"""

106

Set list of module names to preload in forkserver process.

107

108

Modules are imported when the forkserver starts, potentially

109

improving performance by avoiding repeated imports.

110

Only affects 'forkserver' start method.

111

112

Args:

113

module_names: list of module names to preload

114

"""

115

```

116

117

### Serialization Configuration

118

119

Control over object serialization behavior.

120

121

```python { .api }

122

# Context property for controlling serialization

123

@property

124

def reducer(self):

125

"""

126

Get the reducer used for object serialization.

127

128

Returns:

129

module: reduction module (typically dill-enhanced)

130

"""

131

132

@reducer.setter

133

def reducer(self, reduction):

134

"""

135

Set the reducer for object serialization.

136

137

Args:

138

reduction: reduction module to use

139

"""

140

```

141

142

### Advanced Configuration

143

144

Functions for specialized configuration scenarios.

145

146

```python { .api }

147

def allow_connection_pickling():

148

"""

149

Enable pickling of connection objects.

150

151

Allows connection objects to be sent between processes.

152

This is generally not recommended for security reasons.

153

"""

154

155

def freeze_support():

156

"""

157

Add support for frozen executables on Windows.

158

159

Should be called in the main module of programs that use

160

multiprocess and are frozen with tools like py2exe or PyInstaller.

161

"""

162

163

def get_logger():

164

"""

165

Get the logger used by multiprocess.

166

167

Returns:

168

Logger: The multiprocess logger instance

169

"""

170

171

def log_to_stderr(level=None):

172

"""

173

Turn on logging and add a handler which prints to stderr.

174

175

Args:

176

level: Optional logging level to set

177

178

Returns:

179

Logger: The configured logger instance

180

"""

181

```

182

183

## Start Method Details

184

185

### Fork Method

186

187

Available on Unix-like systems (Linux, macOS). Creates child processes by forking the parent process.

188

189

**Characteristics:**

190

- Fast process creation

191

- Inherits parent's memory state

192

- Shares file descriptors and handles

193

- Can have issues with threads and certain libraries

194

- Default on Linux

195

196

**When to use:**

197

- Fast process startup needed

198

- Sharing large amounts of data

199

- Unix-only applications

200

201

### Spawn Method

202

203

Available on all platforms. Creates fresh Python interpreter processes.

204

205

**Characteristics:**

206

- Slower process creation

207

- Clean process state

208

- Better isolation

209

- Required on Windows

210

- Safer with threads

211

- Default on Windows and macOS (recent versions)

212

213

**When to use:**

214

- Cross-platform compatibility needed

215

- Using threading in parent process

216

- Need process isolation

217

- Windows applications

218

219

### Forkserver Method

220

221

Available on Unix-like systems. Uses a server process to create child processes.

222

223

**Characteristics:**

224

- Moderate startup time

225

- Clean process state after server startup

226

- Server process can preload modules

227

- Avoids fork-related issues

228

- Requires additional setup

229

230

**When to use:**

231

- Want benefits of fork with clean state

232

- Using threads that don't work well with fork

233

- Need to preload heavy modules

234

235

## Usage Examples

236

237

### Basic Context Usage

238

239

```python

240

import multiprocess as mp

241

242

# Get default context

243

ctx = mp.get_context()

244

print(f"Default method: {ctx.get_start_method()}")

245

246

# Get specific context

247

spawn_ctx = mp.get_context('spawn')

248

fork_ctx = mp.get_context('fork') # Unix only

249

250

# Use context to create objects

251

with spawn_ctx.Pool(2) as pool:

252

results = pool.map(lambda x: x**2, [1, 2, 3, 4])

253

print(results)

254

```

255

256

### Setting Start Method

257

258

```python

259

import multiprocess as mp

260

261

def worker():

262

print(f"Worker using method: {mp.get_start_method()}")

263

264

if __name__ == '__main__':

265

# Must set start method before creating processes

266

print(f"Available methods: {mp.get_all_start_methods()}")

267

268

# Set start method

269

mp.set_start_method('spawn')

270

print(f"Set method to: {mp.get_start_method()}")

271

272

# Create process

273

p = mp.Process(target=worker)

274

p.start()

275

p.join()

276

```

277

278

### Method Comparison

279

280

```python

281

import multiprocess as mp

282

import time

283

import os

284

285

def simple_worker(method_name):

286

"""Simple worker to test process creation time"""

287

pid = os.getpid()

288

print(f"Worker PID {pid} using {method_name}")

289

return pid

290

291

def benchmark_method(method_name, num_processes=4):

292

"""Benchmark process creation time for a method"""

293

try:

294

ctx = mp.get_context(method_name)

295

except ValueError:

296

print(f"Method {method_name} not available")

297

return None

298

299

start_time = time.time()

300

301

with ctx.Pool(num_processes) as pool:

302

results = pool.map(simple_worker, [method_name] * num_processes)

303

304

end_time = time.time()

305

duration = end_time - start_time

306

307

print(f"{method_name}: {duration:.3f} seconds for {num_processes} processes")

308

return duration

309

310

if __name__ == '__main__':

311

print("Benchmarking start methods:")

312

313

methods = mp.get_all_start_methods()

314

print(f"Available methods: {methods}")

315

316

for method in methods:

317

benchmark_method(method)

318

```

319

320

### Context Isolation

321

322

```python

323

import multiprocess as mp

324

325

# Global variable to test inheritance

326

global_data = "Original data"

327

328

def show_global_data(context_method):

329

"""Show whether global data is inherited"""

330

print(f"Method {context_method}: global_data = '{global_data}'")

331

332

def modify_and_show(context_method):

333

"""Modify global data and show it"""

334

global global_data

335

global_data = f"Modified by {context_method}"

336

print(f"Method {context_method}: modified global_data = '{global_data}'")

337

338

if __name__ == '__main__':

339

# Test different contexts

340

methods = mp.get_all_start_methods()

341

342

for method in methods:

343

try:

344

ctx = mp.get_context(method)

345

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

346

347

# Show original data

348

p1 = ctx.Process(target=show_global_data, args=(method,))

349

p1.start()

350

p1.join()

351

352

# Try to modify data

353

p2 = ctx.Process(target=modify_and_show, args=(method,))

354

p2.start()

355

p2.join()

356

357

# Show data again to see if modification persisted

358

p3 = ctx.Process(target=show_global_data, args=(method,))

359

p3.start()

360

p3.join()

361

362

except ValueError:

363

print(f"Method {method} not available")

364

```

365

366

### Custom Executable Configuration

367

368

```python

369

import multiprocess as mp

370

import sys

371

import subprocess

372

373

def worker_info():

374

"""Show information about the Python executable"""

375

print(f"Executable: {sys.executable}")

376

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

377

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

378

379

if __name__ == '__main__':

380

print("Default executable:")

381

p1 = mp.Process(target=worker_info)

382

p1.start()

383

p1.join()

384

385

# Set custom executable (if available)

386

# This is just an example - in practice you'd use a different Python

387

try:

388

# Try to find another Python executable

389

result = subprocess.run(['which', 'python3'],

390

capture_output=True, text=True)

391

if result.returncode == 0:

392

custom_python = result.stdout.strip()

393

if custom_python != sys.executable:

394

print(f"\nSetting custom executable: {custom_python}")

395

mp.set_executable(custom_python)

396

397

p2 = mp.Process(target=worker_info)

398

p2.start()

399

p2.join()

400

else:

401

print("No different Python executable found")

402

else:

403

print("Could not find alternative Python executable")

404

except Exception as e:

405

print(f"Error setting custom executable: {e}")

406

```

407

408

### Forkserver with Preloading

409

410

```python

411

import multiprocess as mp

412

import time

413

414

# Heavy module to preload

415

import numpy as np

416

import json

417

418

def worker_with_numpy(data):

419

"""Worker that uses numpy - should be faster with preloading"""

420

start_time = time.time()

421

422

# Use numpy (should be already imported in forkserver)

423

arr = np.array(data)

424

result = np.sum(arr ** 2)

425

426

end_time = time.time()

427

print(f"Worker processed {len(data)} items in {end_time - start_time:.3f}s")

428

return result

429

430

if __name__ == '__main__':

431

# Only works on systems that support forkserver

432

if 'forkserver' in mp.get_all_start_methods():

433

# Set forkserver method

434

mp.set_start_method('forkserver')

435

436

# Preload heavy modules in forkserver

437

mp.set_forkserver_preload(['numpy', 'json'])

438

439

print("Using forkserver with preloaded modules")

440

441

# Create some work

442

data_sets = [[i] * 1000 for i in range(1, 6)]

443

444

# Process with preloaded modules

445

start_time = time.time()

446

with mp.Pool(2) as pool:

447

results = pool.map(worker_with_numpy, data_sets)

448

end_time = time.time()

449

450

print(f"Results: {results}")

451

print(f"Total time: {end_time - start_time:.3f}s")

452

else:

453

print("Forkserver method not available on this platform")

454

```

455

456

### Advanced Configuration Example

457

458

```python

459

import multiprocess as mp

460

import os

461

import sys

462

463

class ConfigurableWorker:

464

def __init__(self, config):

465

self.config = config

466

467

def work(self, data):

468

pid = os.getpid()

469

method = mp.get_start_method()

470

471

result = {

472

'pid': pid,

473

'method': method,

474

'data': data,

475

'config': self.config,

476

'processed': data * 2

477

}

478

479

return result

480

481

def create_configured_pool(method='spawn', processes=None, preload=None):

482

"""Create a pool with specific configuration"""

483

484

# Set start method

485

mp.set_start_method(method, force=True)

486

487

# Configure forkserver preloading if applicable

488

if method == 'forkserver' and preload:

489

mp.set_forkserver_preload(preload)

490

491

# Create context

492

ctx = mp.get_context(method)

493

494

# Configuration for workers

495

config = {

496

'method': method,

497

'preload': preload,

498

'python_executable': sys.executable

499

}

500

501

# Create pool with initializer

502

def init_worker():

503

global worker_instance

504

worker_instance = ConfigurableWorker(config)

505

506

def worker_task(data):

507

return worker_instance.work(data)

508

509

pool = ctx.Pool(processes=processes,

510

initializer=init_worker)

511

512

return pool, worker_task

513

514

if __name__ == '__main__':

515

# Test different configurations

516

configs = [

517

{'method': 'spawn', 'processes': 2, 'preload': None},

518

]

519

520

# Add forkserver if available

521

if 'forkserver' in mp.get_all_start_methods():

522

configs.append({

523

'method': 'forkserver',

524

'processes': 2,

525

'preload': ['json', 'os']

526

})

527

528

# Add fork if available

529

if 'fork' in mp.get_all_start_methods():

530

configs.append({

531

'method': 'fork',

532

'processes': 2,

533

'preload': None

534

})

535

536

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

537

538

for config in configs:

539

print(f"\nTesting configuration: {config}")

540

541

try:

542

with create_configured_pool(**config) as (pool, task_func):

543

results = pool.map(task_func, data)

544

545

print("Results:")

546

for result in results:

547

print(f" PID {result['pid']} ({result['method']}): "

548

f"{result['data']} -> {result['processed']}")

549

550

except Exception as e:

551

print(f"Configuration failed: {e}")

552

```

553

554

### Context Best Practices

555

556

```python

557

import multiprocess as mp

558

import logging

559

560

# Configure logging

561

logging.basicConfig(level=logging.INFO)

562

logger = logging.getLogger(__name__)

563

564

class ProcessManager:

565

def __init__(self, method=None, processes=None):

566

self.method = method or self._get_best_method()

567

self.processes = processes or mp.cpu_count()

568

self.context = mp.get_context(self.method)

569

570

logger.info(f"Initialized ProcessManager with method '{self.method}', "

571

f"{self.processes} processes")

572

573

def _get_best_method(self):

574

"""Choose the best start method for the platform"""

575

available = mp.get_all_start_methods()

576

577

# Platform-specific preferences

578

if sys.platform == 'win32':

579

return 'spawn' # Only option on Windows

580

elif sys.platform == 'darwin':

581

return 'spawn' # Recommended on macOS

582

else:

583

# On Linux, prefer forkserver if available, then fork

584

if 'forkserver' in available:

585

return 'forkserver'

586

elif 'fork' in available:

587

return 'fork'

588

else:

589

return 'spawn'

590

591

def create_pool(self, **kwargs):

592

"""Create a pool using the configured context"""

593

return self.context.Pool(processes=self.processes, **kwargs)

594

595

def create_process(self, **kwargs):

596

"""Create a process using the configured context"""

597

return self.context.Process(**kwargs)

598

599

def get_queue(self, **kwargs):

600

"""Create a queue using the configured context"""

601

return self.context.Queue(**kwargs)

602

603

def example_task(x):

604

return x ** 2

605

606

if __name__ == '__main__':

607

import sys

608

609

# Create process manager

610

pm = ProcessManager()

611

612

# Use the manager

613

with pm.create_pool() as pool:

614

data = list(range(10))

615

results = pool.map(example_task, data)

616

logger.info(f"Results: {results}")

617

618

# Create individual processes

619

q = pm.get_queue()

620

621

def worker():

622

q.put(f"Hello from {os.getpid()}")

623

624

processes = []

625

for i in range(3):

626

p = pm.create_process(target=worker)

627

p.start()

628

processes.append(p)

629

630

# Collect results

631

for _ in range(3):

632

message = q.get()

633

logger.info(f"Received: {message}")

634

635

# Wait for processes

636

for p in processes:

637

p.join()

638

639

logger.info("All processes completed")

640

```