or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

configuration.mdexception-handling.mdindex.mdjava-integration.mdjsr223-scripting.mdpython-execution.mdpython-objects.md

exception-handling.mddocs/

0

# Exception Handling

1

2

Jython provides comprehensive exception handling that bridges Python and Java exception systems, allowing seamless error handling across both platforms.

3

4

## PyException Class

5

6

The main exception class that represents Python exceptions in Java.

7

8

```java { .api }

9

public class PyException extends RuntimeException {

10

public PyObject type; // Exception type (e.g., ValueError, TypeError)

11

public PyObject value; // Exception value/message

12

public PyTraceback traceback; // Python traceback information

13

14

// Constructors

15

public PyException();

16

public PyException(PyObject type);

17

public PyException(PyObject type, String value);

18

public PyException(PyObject type, PyObject value);

19

public PyException(PyObject type, PyObject value, PyTraceback traceback);

20

21

// Exception matching and handling

22

public boolean match(PyObject exc);

23

public boolean match(PyObject[] excs);

24

public void normalize();

25

public PyObject getCause();

26

public void setCause(PyObject cause);

27

28

// Traceback handling

29

public void setTraceback(PyTraceback traceback);

30

public void tracebackHere(PyFrame frame);

31

public void tracebackHere(PyFrame frame, boolean isFinally);

32

33

// String representation

34

public String toString();

35

}

36

```

37

38

## Python Exception Types

39

40

All standard Python exceptions are available as static fields in the `Py` class.

41

42

```java { .api }

43

public final class Py {

44

// Base exceptions

45

public static final PyObject Exception;

46

public static final PyObject BaseException;

47

public static final PyObject SystemExit;

48

public static final PyObject KeyboardInterrupt;

49

public static final PyObject GeneratorExit;

50

51

// Common exceptions

52

public static final PyObject TypeError;

53

public static final PyObject ValueError;

54

public static final PyObject RuntimeError;

55

public static final PyObject AttributeError;

56

public static final PyObject KeyError;

57

public static final PyObject IndexError;

58

public static final PyObject NameError;

59

public static final PyObject ImportError;

60

public static final PyObject IOError;

61

public static final PyObject OSError;

62

public static final PyObject SyntaxError;

63

public static final PyObject IndentationError;

64

public static final PyObject SystemError;

65

public static final PyObject MemoryError;

66

public static final PyObject OverflowError;

67

public static final PyObject ZeroDivisionError;

68

public static final PyObject AssertionError;

69

public static final PyObject LookupError;

70

public static final PyObject StopIteration;

71

72

// Warning types

73

public static final PyObject Warning;

74

public static final PyObject UserWarning;

75

public static final PyObject DeprecationWarning;

76

public static final PyObject SyntaxWarning;

77

public static final PyObject RuntimeWarning;

78

public static final PyObject FutureWarning;

79

public static final PyObject ImportWarning;

80

public static final PyObject UnicodeWarning;

81

public static final PyObject BytesWarning;

82

public static final PyObject ResourceWarning;

83

}

84

```

85

86

## Exception Factory Methods

87

88

Convenient factory methods for creating Python exceptions.

89

90

```java { .api }

91

public final class Py {

92

// Exception creation

93

public static PyException TypeError(String message);

94

public static PyException ValueError(String message);

95

public static PyException RuntimeError(String message);

96

public static PyException AttributeError(String message);

97

public static PyException KeyError(String message);

98

public static PyException IndexError(String message);

99

public static PyException NameError(String message);

100

public static PyException ImportError(String message);

101

public static PyException IOError(String message);

102

public static PyException OSError(String message);

103

public static PyException SyntaxError(String message);

104

public static PyException SystemError(String message);

105

public static PyException MemoryError(String message);

106

public static PyException OverflowError(String message);

107

public static PyException ZeroDivisionError(String message);

108

public static PyException AssertionError(String message);

109

public static PyException StopIteration();

110

public static PyException StopIteration(String message);

111

112

// Exception creation with custom value

113

public static PyException makeException(PyObject type, PyObject value);

114

public static PyException makeException(PyObject type, PyObject value, PyTraceback traceback);

115

}

116

```

117

118

## Traceback Information

119

120

Python traceback information for debugging.

121

122

```java { .api }

123

public class PyTraceback extends PyObject {

124

public PyTraceback tb_next; // Next traceback frame

125

public PyFrame tb_frame; // Frame object

126

public int tb_lineno; // Line number

127

128

public PyTraceback(PyFrame frame);

129

public PyTraceback(PyTraceback next, PyFrame frame);

130

131

// Traceback manipulation

132

public void dumpStack();

133

public void dumpStack(StringBuilder buffer);

134

}

135

```

136

137

## Exception Handling Examples

138

139

### Catching Python Exceptions in Java

140

141

```java

142

import org.python.core.*;

143

import org.python.util.PythonInterpreter;

144

145

PythonInterpreter interp = new PythonInterpreter();

146

147

try {

148

interp.exec("raise ValueError('Something went wrong')");

149

} catch (PyException e) {

150

// Check exception type

151

if (e.match(Py.ValueError)) {

152

System.out.println("Caught ValueError: " + e.value);

153

} else if (e.match(Py.TypeError)) {

154

System.out.println("Caught TypeError: " + e.value);

155

} else {

156

System.out.println("Caught other exception: " + e.type + " - " + e.value);

157

}

158

159

// Print Python traceback

160

if (e.traceback != null) {

161

e.traceback.dumpStack();

162

}

163

}

164

165

interp.close();

166

```

167

168

### Multiple Exception Types

169

170

```java

171

try {

172

interp.exec("undefined_variable + 1");

173

} catch (PyException e) {

174

// Check against multiple exception types

175

PyObject[] commonExceptions = {Py.NameError, Py.TypeError, Py.ValueError};

176

177

if (e.match(commonExceptions)) {

178

System.out.println("Caught common exception: " + e.type);

179

} else {

180

System.out.println("Caught unexpected exception: " + e.type);

181

throw e; // Re-raise if not handled

182

}

183

}

184

```

185

186

### Accessing Exception Details

187

188

```java

189

try {

190

interp.exec("""

191

try:

192

x = 10 / 0

193

except ZeroDivisionError as e:

194

raise ValueError("Custom message") from e

195

""");

196

} catch (PyException e) {

197

System.out.println("Exception type: " + e.type);

198

System.out.println("Exception value: " + e.value);

199

200

// Get the original cause if available

201

PyObject cause = e.getCause();

202

if (cause != null && cause != Py.None) {

203

System.out.println("Caused by: " + cause);

204

}

205

206

// Print full traceback

207

System.out.println("Full traceback:");

208

System.out.println(e.toString());

209

}

210

```

211

212

## Raising Python Exceptions from Java

213

214

### Using Factory Methods

215

216

```java

217

// Raise exceptions from Java code

218

PythonInterpreter interp = new PythonInterpreter();

219

220

// Set up Python function that calls Java

221

interp.exec("""

222

def test_function(value):

223

return java_function(value)

224

""");

225

226

// Define Java function that can raise Python exceptions

227

interp.set("java_function", new PyObject() {

228

public PyObject __call__(PyObject[] args, String[] keywords) {

229

if (args.length == 0) {

230

throw Py.TypeError("java_function() missing required argument");

231

}

232

233

PyObject arg = args[0];

234

if (arg instanceof PyInteger) {

235

int value = ((PyInteger) arg).getValue();

236

if (value < 0) {

237

throw Py.ValueError("value must be non-negative");

238

}

239

if (value == 0) {

240

throw Py.ZeroDivisionError("cannot divide by zero");

241

}

242

return Py.newInteger(100 / value);

243

} else {

244

throw Py.TypeError("expected integer argument");

245

}

246

}

247

});

248

249

// Test the exception handling

250

try {

251

interp.exec("result = test_function(-5)");

252

} catch (PyException e) {

253

if (e.match(Py.ValueError)) {

254

System.out.println("Validation error: " + e.value);

255

}

256

}

257

```

258

259

### Custom Exception Classes

260

261

```java

262

// Create custom Python exception class from Java

263

interp.exec("""

264

class CustomError(Exception):

265

def __init__(self, message, error_code=None):

266

super().__init__(message)

267

self.error_code = error_code

268

""");

269

270

// Get the custom exception class

271

PyObject customErrorClass = interp.get("CustomError");

272

273

// Raise custom exception from Java

274

PyObject[] args = {Py.newString("Custom error occurred"), Py.newInteger(404)};

275

PyException customException = new PyException(customErrorClass,

276

customErrorClass.__call__(args));

277

278

throw customException;

279

```

280

281

## Java Exception Integration

282

283

### Java Exceptions in Python Code

284

285

```java

286

// Java method that throws checked exception

287

class FileProcessor {

288

public static String readFile(String filename) throws IOException {

289

if (!new File(filename).exists()) {

290

throw new IOException("File not found: " + filename);

291

}

292

return Files.readString(Paths.get(filename));

293

}

294

}

295

296

PythonInterpreter interp = new PythonInterpreter();

297

interp.set("FileProcessor", FileProcessor.class);

298

299

interp.exec("""

300

try:

301

content = FileProcessor.readFile("nonexistent.txt")

302

except Exception as e:

303

print("Caught Java exception:", type(e).__name__)

304

print("Message:", str(e))

305

306

# Java exceptions appear as Python exceptions

307

import traceback

308

traceback.print_exc()

309

""");

310

```

311

312

### Converting Java Exceptions to Python

313

314

```java

315

// Automatic conversion of Java exceptions

316

try {

317

interp.exec("""

318

from java.lang import Integer

319

# This will throw NumberFormatException

320

num = Integer.parseInt("not_a_number")

321

""");

322

} catch (PyException e) {

323

// Java NumberFormatException becomes Python exception

324

System.out.println("Java exception as Python: " + e.type);

325

System.out.println("Message: " + e.value);

326

}

327

```

328

329

## Exception Configuration

330

331

### Controlling Exception Display

332

333

```java

334

import org.python.core.Options;

335

336

// Show Java stack traces in Python exceptions

337

Options.showJavaExceptions = true;

338

339

// Include Java stack traces in Python tracebacks

340

Options.includeJavaStackInExceptions = true;

341

342

// Show Python proxy exceptions

343

Options.showPythonProxyExceptions = true;

344

345

PythonInterpreter interp = new PythonInterpreter();

346

347

try {

348

interp.exec("""

349

from java.util import ArrayList

350

list = ArrayList()

351

# This will show Java stack trace if enabled

352

list.get(10) # IndexOutOfBoundsException

353

""");

354

} catch (PyException e) {

355

System.out.println("Exception with Java details: " + e);

356

}

357

358

interp.close();

359

```

360

361

## Advanced Exception Patterns

362

363

### Exception Context Managers

364

365

```java

366

// Exception handling with context managers

367

interp.exec("""

368

class ExceptionHandler:

369

def __enter__(self):

370

print("Entering exception context")

371

return self

372

373

def __exit__(self, exc_type, exc_val, exc_tb):

374

if exc_type:

375

print(f"Handling {exc_type.__name__}: {exc_val}")

376

return True # Suppress exception

377

print("Exiting normally")

378

return False

379

""");

380

381

// Use the context manager

382

interp.exec("""

383

with ExceptionHandler():

384

raise ValueError("This will be suppressed")

385

386

print("Execution continues after context manager")

387

""");

388

```

389

390

### Exception Chaining

391

392

```java

393

// Python-style exception chaining

394

try {

395

interp.exec("""

396

def inner_function():

397

raise ValueError("Original error")

398

399

def outer_function():

400

try:

401

inner_function()

402

except ValueError as e:

403

raise RuntimeError("Wrapper error") from e

404

405

outer_function()

406

""");

407

} catch (PyException e) {

408

System.out.println("Main exception: " + e.type + " - " + e.value);

409

410

// Check for chained exception

411

PyObject cause = e.getCause();

412

if (cause != null && cause != Py.None) {

413

System.out.println("Caused by: " + cause);

414

}

415

}

416

```

417

418

### Custom Exception Handler

419

420

```java

421

public class JythonExceptionHandler {

422

private PythonInterpreter interp;

423

424

public JythonExceptionHandler(PythonInterpreter interp) {

425

this.interp = interp;

426

}

427

428

public Object safeExecute(String code) {

429

try {

430

return interp.eval(code);

431

} catch (PyException e) {

432

return handlePythonException(e);

433

} catch (Exception e) {

434

return handleJavaException(e);

435

}

436

}

437

438

private Object handlePythonException(PyException e) {

439

if (e.match(Py.SyntaxError)) {

440

System.err.println("Syntax error in Python code: " + e.value);

441

return null;

442

} else if (e.match(Py.NameError)) {

443

System.err.println("Undefined variable: " + e.value);

444

return null;

445

} else if (e.match(Py.TypeError)) {

446

System.err.println("Type error: " + e.value);

447

return null;

448

} else {

449

System.err.println("Unhandled Python exception: " + e.type + " - " + e.value);

450

e.printStackTrace();

451

return null;

452

}

453

}

454

455

private Object handleJavaException(Exception e) {

456

System.err.println("Java exception: " + e.getMessage());

457

e.printStackTrace();

458

return null;

459

}

460

}

461

462

// Usage:

463

JythonExceptionHandler handler = new JythonExceptionHandler(interp);

464

Object result = handler.safeExecute("undefined_variable");

465

```

466

467

## Error Recovery Patterns

468

469

### Graceful Degradation

470

471

```java

472

public class RobustJythonService {

473

private PythonInterpreter interp;

474

475

public String processData(String data) {

476

String fallbackResult = "Error processing data";

477

478

try {

479

interp.set("input_data", data);

480

PyObject result = interp.eval("process_input(input_data)");

481

return result.toString();

482

} catch (PyException e) {

483

if (e.match(Py.ImportError)) {

484

// Module not available, use Java fallback

485

return processDataFallback(data);

486

} else if (e.match(Py.ValueError)) {

487

// Invalid data, return error message

488

return "Invalid input: " + e.value;

489

} else {

490

// Log error and return fallback

491

System.err.println("Python processing failed: " + e);

492

return fallbackResult;

493

}

494

}

495

}

496

497

private String processDataFallback(String data) {

498

// Java implementation as fallback

499

return "Processed by Java: " + data.toUpperCase();

500

}

501

}

502

```

503

504

### Retry with Different Approaches

505

506

```java

507

public class RetryingJythonExecutor {

508

private PythonInterpreter interp;

509

510

public Object executeWithRetry(String primaryCode, String fallbackCode) {

511

// Try primary approach

512

try {

513

return interp.eval(primaryCode);

514

} catch (PyException e) {

515

System.out.println("Primary approach failed: " + e.value);

516

517

// Try fallback approach

518

try {

519

return interp.eval(fallbackCode);

520

} catch (PyException fallbackError) {

521

System.err.println("Both approaches failed");

522

System.err.println("Primary: " + e.value);

523

System.err.println("Fallback: " + fallbackError.value);

524

throw fallbackError;

525

}

526

}

527

}

528

}

529

```

530

531

## Debugging Exception Information

532

533

### Detailed Exception Analysis

534

535

```java

536

public class ExceptionAnalyzer {

537

public static void analyzeException(PyException e) {

538

System.out.println("=== Exception Analysis ===");

539

System.out.println("Type: " + e.type);

540

System.out.println("Value: " + e.value);

541

System.out.println("Message: " + e.getMessage());

542

543

// Java stack trace

544

System.out.println("\nJava Stack Trace:");

545

e.printStackTrace();

546

547

// Python traceback

548

if (e.traceback != null) {

549

System.out.println("\nPython Traceback:");

550

e.traceback.dumpStack();

551

}

552

553

// Exception cause chain

554

Throwable cause = e.getCause();

555

int level = 1;

556

while (cause != null) {

557

System.out.println("\nCause Level " + level + ": " + cause.getMessage());

558

cause = cause.getCause();

559

level++;

560

}

561

562

System.out.println("=== End Analysis ===");

563

}

564

}

565

566

// Usage:

567

try {

568

interp.exec("complex_operation()");

569

} catch (PyException e) {

570

ExceptionAnalyzer.analyzeException(e);

571

}

572

```