or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

exceptions.mdindex.mdinitialization.mdmemory-management.mdmodules.mdobjects.mdutilities.md

exceptions.mddocs/

0

# Exception Handling

1

2

Complete Python exception system integration allowing Java applications to handle Python errors, set Python exceptions from Java code, and work with Python's warning system. This provides seamless error handling between Java and Python runtimes.

3

4

## Capabilities

5

6

### Exception State Management

7

8

Core functions for checking and managing Python exception state.

9

10

```java { .api }

11

/**

12

* Check if an exception is currently set

13

* @return Exception object if set, NULL otherwise

14

*/

15

public static native PyObject PyErr_Occurred();

16

17

/**

18

* Clear the current exception state

19

*/

20

public static native void PyErr_Clear();

21

22

/**

23

* Check if exception matches specific type

24

* @param exc - Exception to check

25

* @param type - Exception type to match against

26

* @return Non-zero if exception matches type

27

*/

28

public static native int PyErr_ExceptionMatches(PyObject exc);

29

30

/**

31

* Check if current exception matches specific type

32

* @param type - Exception type to check against

33

* @return Non-zero if current exception matches type

34

*/

35

public static native int PyErr_GivenExceptionMatches(PyObject type);

36

```

37

38

**Usage Example:**

39

40

```java

41

import static org.bytedeco.cpython.global.python.*;

42

43

// Call a Python function that might raise an exception

44

PyObject result = PyRun_SimpleString("1 / 0"); // Division by zero

45

46

// Check for exceptions

47

if (PyErr_Occurred() != null) {

48

System.out.println("Python exception occurred!");

49

50

// Check specific exception type

51

if (PyErr_ExceptionMatches(PyExc_ZeroDivisionError())) {

52

System.out.println("Division by zero error");

53

}

54

55

// Clear the exception

56

PyErr_Clear();

57

}

58

```

59

60

### Setting Exceptions

61

62

Functions for setting Python exceptions from Java code.

63

64

```java { .api }

65

/**

66

* Set exception with no value (just the type)

67

* @param exception - Exception type to set

68

*/

69

public static native void PyErr_SetNone(PyObject exception);

70

71

/**

72

* Set exception with specific value object

73

* @param exception - Exception type

74

* @param value - Exception value object

75

*/

76

public static native void PyErr_SetObject(PyObject exception, PyObject value);

77

78

/**

79

* Set exception with string message

80

* @param exception - Exception type

81

* @param message - Error message string

82

*/

83

public static native void PyErr_SetString(PyObject exception, String message);

84

85

/**

86

* Set exception using formatted message

87

* @param exception - Exception type

88

* @param format - Printf-style format string

89

* @param args - Format arguments

90

*/

91

public static native PyObject PyErr_Format(PyObject exception, String format, Object... args);

92

93

/**

94

* Set MemoryError exception

95

*/

96

public static native PyObject PyErr_NoMemory();

97

98

/**

99

* Set exception for bad argument to function

100

*/

101

public static native PyObject PyErr_BadArgument();

102

103

/**

104

* Set exception for bad internal call

105

*/

106

public static native PyObject PyErr_BadInternalCall();

107

```

108

109

**Usage Example:**

110

111

```java

112

// Set a custom exception

113

PyErr_SetString(PyExc_ValueError(), "Invalid input parameter");

114

115

// Set formatted exception

116

PyErr_Format(PyExc_TypeError(), "Expected %s, got %s", "int", "str");

117

118

// Set memory error

119

PyErr_NoMemory();

120

121

// Set exception with object value

122

PyObject errorDetails = PyDict_New();

123

PyDict_SetItemString(errorDetails, "code", PyLong_FromLong(404));

124

PyErr_SetObject(PyExc_RuntimeError(), errorDetails);

125

```

126

127

### Exception Fetch and Restore

128

129

Advanced exception handling for preserving and restoring exception state.

130

131

```java { .api }

132

/**

133

* Fetch current exception info (clears current exception)

134

* @param type - Pointer to receive exception type

135

* @param value - Pointer to receive exception value

136

* @param traceback - Pointer to receive traceback object

137

*/

138

public static native void PyErr_Fetch(PointerPointer type, PointerPointer value, PointerPointer traceback);

139

140

/**

141

* Restore exception info (sets current exception)

142

* @param type - Exception type (can be NULL)

143

* @param value - Exception value (can be NULL)

144

* @param traceback - Traceback object (can be NULL)

145

*/

146

public static native void PyErr_Restore(PyObject type, PyObject value, PyObject traceback);

147

148

/**

149

* Normalize exception info (converts strings to proper exception objects)

150

* @param type - Pointer to exception type (modified)

151

* @param value - Pointer to exception value (modified)

152

* @param traceback - Pointer to traceback (modified)

153

*/

154

public static native void PyErr_NormalizeException(PointerPointer type, PointerPointer value, PointerPointer traceback);

155

```

156

157

### New Exception Handling (Python 3.12+)

158

159

Modern exception handling API introduced in Python 3.12.

160

161

```java { .api }

162

/**

163

* Get currently raised exception (new API)

164

* @return Current exception object, or NULL if none

165

*/

166

public static native PyObject PyErr_GetRaisedException();

167

168

/**

169

* Set currently raised exception (new API)

170

* @param exc - Exception object to set (can be NULL to clear)

171

*/

172

public static native void PyErr_SetRaisedException(PyObject exc);

173

174

/**

175

* Get currently handled exception

176

* @return Currently handled exception, or NULL if none

177

*/

178

public static native PyObject PyErr_GetHandledException();

179

180

/**

181

* Set currently handled exception

182

* @param exc - Exception object to set as handled

183

*/

184

public static native void PyErr_SetHandledException(PyObject exc);

185

```

186

187

**Usage Example:**

188

189

```java

190

// Modern exception handling pattern

191

PyObject exception = PyErr_GetRaisedException();

192

if (exception != null) {

193

// Process the exception

194

System.out.println("Handling exception: " + exception);

195

196

// Optionally re-raise or clear

197

PyErr_SetRaisedException(null); // Clear

198

// or PyErr_SetRaisedException(exception); // Re-raise

199

}

200

```

201

202

### Warning System

203

204

Python's warning system integration for handling warnings from Java.

205

206

```java { .api }

207

/**

208

* Issue a warning

209

* @param category - Warning category (or NULL for default)

210

* @param message - Warning message

211

* @param stack_level - Stack level for warning location

212

* @return 0 on success, -1 on error

213

*/

214

public static native int PyErr_WarnEx(PyObject category, String message, long stack_level);

215

216

/**

217

* Issue a formatted warning

218

* @param category - Warning category

219

* @param stack_level - Stack level for warning location

220

* @param format - Printf-style format string

221

* @param args - Format arguments

222

* @return 0 on success, -1 on error

223

*/

224

public static native int PyErr_WarnFormat(PyObject category, long stack_level, String format, Object... args);

225

226

/**

227

* Issue a resource warning

228

* @param source - Source object causing the warning

229

* @param stack_level - Stack level for warning location

230

* @param format - Printf-style format string

231

* @param args - Format arguments

232

* @return 0 on success, -1 on error

233

*/

234

public static native int PyErr_ResourceWarning(PyObject source, long stack_level, String format, Object... args);

235

236

/**

237

* Issue an explicit warning with full control

238

* @param category - Warning category

239

* @param message - Warning message

240

* @param filename - Source filename

241

* @param lineno - Line number

242

* @param module - Module name

243

* @param registry - Warning registry

244

* @return 0 on success, -1 on error

245

*/

246

public static native int PyErr_WarnExplicit(PyObject category, String message, String filename,

247

int lineno, String module, PyObject registry);

248

```

249

250

**Usage Example:**

251

252

```java

253

// Issue a deprecation warning

254

int result = PyErr_WarnEx(PyExc_DeprecationWarning(),

255

"This function is deprecated", 1);

256

257

if (result < 0) {

258

// Warning caused an exception (warnings treated as errors)

259

PyErr_Clear();

260

}

261

262

// Issue formatted warning

263

PyErr_WarnFormat(PyExc_UserWarning(), 2,

264

"Value %d is outside expected range", 150);

265

266

// Resource warning for unclosed file

267

PyErr_ResourceWarning(fileObject, 1,

268

"unclosed file %s", filename);

269

```

270

271

### Built-in Exception Types

272

273

Access to all standard Python exception types.

274

275

```java { .api }

276

// Base exceptions

277

public static native PyObject PyExc_BaseException();

278

public static native PyObject PyExc_Exception();

279

public static native PyObject PyExc_ArithmeticError();

280

public static native PyObject PyExc_LookupError();

281

282

// Common exceptions

283

public static native PyObject PyExc_AttributeError();

284

public static native PyObject PyExc_EOFError();

285

public static native PyObject PyExc_ImportError();

286

public static native PyObject PyExc_IndexError();

287

public static native PyObject PyExc_KeyError();

288

public static native PyObject PyExc_KeyboardInterrupt();

289

public static native PyObject PyExc_MemoryError();

290

public static native PyObject PyExc_NameError();

291

public static native PyObject PyExc_OSError();

292

public static native PyObject PyExc_RuntimeError();

293

public static native PyObject PyExc_StopIteration();

294

public static native PyObject PyExc_SyntaxError();

295

public static native PyObject PyExc_SystemError();

296

public static native PyObject PyExc_SystemExit();

297

public static native PyObject PyExc_TypeError();

298

public static native PyObject PyExc_ValueError();

299

public static native PyObject PyExc_ZeroDivisionError();

300

301

// Warning categories

302

public static native PyObject PyExc_Warning();

303

public static native PyObject PyExc_UserWarning();

304

public static native PyObject PyExc_DeprecationWarning();

305

public static native PyObject PyExc_PendingDeprecationWarning();

306

public static native PyObject PyExc_SyntaxWarning();

307

public static native PyObject PyExc_RuntimeWarning();

308

public static native PyObject PyExc_FutureWarning();

309

public static native PyObject PyExc_ImportWarning();

310

public static native PyObject PyExc_UnicodeWarning();

311

public static native PyObject PyExc_BytesWarning();

312

public static native PyObject PyExc_ResourceWarning();

313

```

314

315

## Exception Object Types

316

317

```java { .api }

318

/**

319

* Base exception object structure

320

*/

321

class PyBaseExceptionObject extends PyObject { }

322

323

/**

324

* Attribute error exception

325

*/

326

class PyAttributeErrorObject extends PyBaseExceptionObject { }

327

328

/**

329

* Import error exception

330

*/

331

class PyImportErrorObject extends PyBaseExceptionObject { }

332

333

/**

334

* Name error exception

335

*/

336

class PyNameErrorObject extends PyBaseExceptionObject { }

337

338

/**

339

* OS error exception

340

*/

341

class PyOSErrorObject extends PyBaseExceptionObject { }

342

343

/**

344

* Syntax error exception

345

*/

346

class PySyntaxErrorObject extends PyBaseExceptionObject { }

347

348

/**

349

* System exit exception

350

*/

351

class PySystemExitObject extends PyBaseExceptionObject { }

352

353

/**

354

* Unicode error exception

355

*/

356

class PyUnicodeErrorObject extends PyBaseExceptionObject { }

357

```

358

359

## Advanced Exception Handling Patterns

360

361

### Exception Context Preservation

362

363

```java

364

// Save current exception state before calling risky operation

365

PointerPointer savedType = new PointerPointer(1);

366

PointerPointer savedValue = new PointerPointer(1);

367

PointerPointer savedTraceback = new PointerPointer(1);

368

369

PyErr_Fetch(savedType, savedValue, savedTraceback);

370

371

try {

372

// Risky operation that might set different exception

373

PyObject result = riskyPythonOperation();

374

375

// If operation succeeded, restore original exception

376

if (PyErr_Occurred() == null) {

377

PyErr_Restore(new PyObject(savedType.get()),

378

new PyObject(savedValue.get()),

379

new PyObject(savedTraceback.get()));

380

}

381

382

} catch (Exception e) {

383

// Handle Java exception, but preserve Python exception

384

PyErr_Restore(new PyObject(savedType.get()),

385

new PyObject(savedValue.get()),

386

new PyObject(savedTraceback.get()));

387

throw e;

388

}

389

```

390

391

### Custom Exception Classes

392

393

```java

394

// Create custom exception type (typically done during module initialization)

395

public PyObject createCustomException(String name, String docstring) {

396

// Create exception class

397

PyObject exceptionClass = PyErr_NewException(name, PyExc_Exception(), null);

398

399

if (exceptionClass != null && docstring != null) {

400

// Set docstring

401

PyObject doc = PyUnicode_FromString(docstring);

402

PyObject_SetAttrString(exceptionClass, "__doc__", doc);

403

}

404

405

return exceptionClass;

406

}

407

```

408

409

### Exception Chaining

410

411

```java

412

// Demonstrate exception chaining (raise ... from ...)

413

try {

414

// Original operation that fails

415

PyObject result = PyLong_FromString("not_a_number", null, 10);

416

417

} catch (Exception e) {

418

// Chain with new exception

419

PyErr_SetString(PyExc_ValueError(), "Failed to process input");

420

421

// The original exception becomes the __cause__

422

// This is handled automatically by Python's exception system

423

}

424

```

425

426

### Comprehensive Error Handling

427

428

```java

429

public class PythonExceptionHandler {

430

431

public static boolean handlePythonError() {

432

if (PyErr_Occurred() == null) {

433

return false; // No error

434

}

435

436

// Get exception information

437

PointerPointer type = new PointerPointer(1);

438

PointerPointer value = new PointerPointer(1);

439

PointerPointer traceback = new PointerPointer(1);

440

441

PyErr_Fetch(type, value, traceback);

442

PyErr_NormalizeException(type, value, traceback);

443

444

PyObject exceptionType = new PyObject(type.get());

445

PyObject exceptionValue = new PyObject(value.get());

446

PyObject exceptionTraceback = new PyObject(traceback.get());

447

448

try {

449

// Log exception details

450

if (PyErr_GivenExceptionMatches(exceptionType, PyExc_ValueError())) {

451

System.err.println("ValueError occurred");

452

} else if (PyErr_GivenExceptionMatches(exceptionType, PyExc_TypeError())) {

453

System.err.println("TypeError occurred");

454

} else {

455

System.err.println("Other exception occurred");

456

}

457

458

// Get exception message

459

if (exceptionValue != null) {

460

PyObject strRepr = PyObject_Str(exceptionValue);

461

if (strRepr != null) {

462

// Convert to Java string and log

463

System.err.println("Exception message: " + strRepr);

464

}

465

}

466

467

return true; // Exception handled

468

469

} finally {

470

// Clean up or re-raise if needed

471

// PyErr_Restore(exceptionType, exceptionValue, exceptionTraceback);

472

}

473

}

474

}

475

```

476

477

### Warning Configuration

478

479

```java

480

// Configure warning behavior

481

public void configureWarnings() {

482

// Import warnings module

483

PyObject warningsModule = PyImport_ImportModule("warnings");

484

485

if (warningsModule != null) {

486

// Set warnings to be treated as errors

487

PyObject filterwarnings = PyObject_GetAttrString(warningsModule, "filterwarnings");

488

489

if (filterwarnings != null) {

490

PyObject args = PyTuple_New(1);

491

PyTuple_SetItem(args, 0, PyUnicode_FromString("error"));

492

493

PyObject result = PyObject_CallObject(filterwarnings, args);

494

495

if (result == null) {

496

// Handle error in warning configuration

497

PyErr_Clear();

498

}

499

}

500

}

501

}

502

```

503

504

## Integration with Java Exception Handling

505

506

### Translating Python Exceptions to Java

507

508

```java

509

public class PythonException extends RuntimeException {

510

private final String pythonExceptionType;

511

private final PyObject pythonException;

512

513

public PythonException(String type, String message, PyObject exception) {

514

super(message);

515

this.pythonExceptionType = type;

516

this.pythonException = exception;

517

}

518

519

public static PythonException fromPythonError() {

520

if (PyErr_Occurred() == null) {

521

return null;

522

}

523

524

// Extract exception details

525

PyObject exception = PyErr_GetRaisedException();

526

PyObject typeName = PyObject_GetAttrString(Py_TYPE(exception), "__name__");

527

PyObject message = PyObject_Str(exception);

528

529

String typeStr = (typeName != null) ? PyUnicode_AsUTF8(typeName) : "Unknown";

530

String msgStr = (message != null) ? PyUnicode_AsUTF8(message) : "No message";

531

532

return new PythonException(typeStr, msgStr, exception);

533

}

534

}

535

536

// Usage

537

public void callPython() throws PythonException {

538

PyRun_SimpleString("raise ValueError('Something went wrong')");

539

540

PythonException pe = PythonException.fromPythonError();

541

if (pe != null) {

542

throw pe;

543

}

544

}

545

```

546

547

## Important Notes

548

549

### Exception Ownership

550

551

When fetching exceptions with `PyErr_Fetch()`, the caller receives ownership of the exception objects and must manage their references appropriately.

552

553

### Thread Safety

554

555

Exception state is thread-specific. Each thread has its own exception state that doesn't interfere with other threads.

556

557

### Performance Considerations

558

559

- Exception checking is fast when no exception is set

560

- Avoid unnecessary exception fetching/restoration in performance-critical code

561

- Clear exceptions promptly to avoid confusion

562

563

### Error Propagation

564

565

Always check for Python exceptions after calling Python C API functions, especially when calling from Java code that doesn't expect Python exceptions.