or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

advanced-features.mdcore-binding.mdexception-handling.mdindex.mdnumpy-integration.mdpython-package.mdstl-integration.mdtype-system.md

exception-handling.mddocs/

0

# Exception Handling

1

2

pybind11 provides seamless translation between C++ exceptions and Python exceptions, allowing natural error handling across the language boundary. It supports both automatic translation of standard exceptions and registration of custom exception types.

3

4

## Capabilities

5

6

### Automatic Exception Translation

7

8

Standard C++ exceptions are automatically translated to appropriate Python exceptions.

9

10

```cpp { .api }

11

// Automatic translations:

12

// std::exception -> RuntimeError

13

// std::bad_alloc -> MemoryError

14

// std::domain_error -> ValueError

15

// std::invalid_argument -> ValueError

16

// std::length_error -> ValueError

17

// std::out_of_range -> IndexError

18

// std::range_error -> ValueError

19

// std::overflow_error -> OverflowError

20

// std::underflow_error -> ArithmeticError

21

```

22

23

### Python Exception Capture

24

25

Capture and handle Python exceptions in C++ code.

26

27

```cpp { .api }

28

class error_already_set : public std::exception {

29

public:

30

// Construct from current Python exception state

31

error_already_set();

32

33

// Query exception information

34

bool matches(handle exc_type) const;

35

const char* what() const noexcept override;

36

37

// Access exception components

38

object type() const;

39

object value() const;

40

object trace() const;

41

42

// Control exception state

43

void restore(); // Restore exception to Python

44

void discard_as_unraisable(object err_context);

45

46

// Static utilities

47

static bool matches(handle exc_type);

48

static void clear();

49

};

50

```

51

52

### Built-in Python Exception Types

53

54

Wrapper classes for standard Python exception types.

55

56

```cpp { .api }

57

class builtin_exception : public object {

58

// Base class for Python built-in exceptions

59

};

60

61

class stop_iteration : public builtin_exception {

62

// Python StopIteration exception

63

public:

64

stop_iteration();

65

stop_iteration(const char* what);

66

stop_iteration(const std::string& what);

67

};

68

69

class index_error : public builtin_exception {

70

// Python IndexError exception

71

public:

72

index_error();

73

index_error(const char* what);

74

index_error(const std::string& what);

75

};

76

77

class key_error : public builtin_exception {

78

// Python KeyError exception

79

public:

80

key_error();

81

key_error(const char* what);

82

key_error(const std::string& what);

83

};

84

85

class value_error : public builtin_exception {

86

// Python ValueError exception

87

public:

88

value_error();

89

value_error(const char* what);

90

value_error(const std::string& what);

91

};

92

93

class type_error : public builtin_exception {

94

// Python TypeError exception

95

public:

96

type_error();

97

type_error(const char* what);

98

type_error(const std::string& what);

99

};

100

101

class attribute_error : public builtin_exception {

102

// Python AttributeError exception

103

public:

104

attribute_error();

105

attribute_error(const char* what);

106

attribute_error(const std::string& what);

107

};

108

```

109

110

### Custom Exception Registration

111

112

Register custom C++ exception types for automatic translation.

113

114

```cpp { .api }

115

// Register custom exception type

116

template<typename CppException>

117

exception<CppException>& register_exception(module_ &m, const char *name,

118

handle base = PyExc_Exception);

119

120

// Exception class template for custom types

121

template<typename CppException>

122

class exception : public builtin_exception {

123

public:

124

exception(handle scope, const char *name, handle base = handle());

125

126

// Set translator function

127

void set_translator(std::function<void(const CppException&)> translator);

128

};

129

```

130

131

### Exception Translation Utilities

132

133

Utilities for handling exception translation and error states.

134

135

```cpp { .api }

136

// Register exception translator

137

template<typename CppException>

138

void register_exception_translator(std::function<void(const CppException&)> translator);

139

140

// Manually raise Python exceptions

141

[[noreturn]] void pybind11_fail(const char* reason);

142

[[noreturn]] void pybind11_fail(const std::string& reason);

143

144

// Check for Python errors

145

bool PyErr_Occurred();

146

void PyErr_Clear();

147

void PyErr_Print();

148

149

// Exception context management

150

class error_scope {

151

public:

152

error_scope();

153

~error_scope();

154

155

bool has_error() const;

156

error_already_set get_error();

157

};

158

```

159

160

### Casting Exceptions

161

162

Special exception type for type casting failures.

163

164

```cpp { .api }

165

class cast_error : public std::runtime_error {

166

// Thrown when type casting fails

167

public:

168

cast_error(const std::string& message);

169

cast_error(const char* message);

170

};

171

172

// Reference casting failure

173

class reference_cast_error : public cast_error {

174

public:

175

reference_cast_error(const std::string& message);

176

};

177

```

178

179

## Usage Examples

180

181

### Basic Exception Handling

182

183

```cpp

184

#include <pybind11/pybind11.h>

185

#include <stdexcept>

186

187

namespace py = pybind11;

188

189

int divide(int a, int b) {

190

if (b == 0) {

191

throw std::invalid_argument("Division by zero");

192

}

193

return a / b;

194

}

195

196

std::string access_vector(const std::vector<std::string>& vec, size_t index) {

197

if (index >= vec.size()) {

198

throw std::out_of_range("Index out of range");

199

}

200

return vec[index];

201

}

202

203

PYBIND11_MODULE(example, m) {

204

// These exceptions are automatically translated:

205

// std::invalid_argument -> ValueError

206

// std::out_of_range -> IndexError

207

m.def("divide", &divide);

208

m.def("access_vector", &access_vector);

209

}

210

```

211

212

### Custom Exception Types

213

214

```cpp

215

#include <pybind11/pybind11.h>

216

217

namespace py = pybind11;

218

219

// Custom C++ exception

220

class NetworkError : public std::runtime_error {

221

public:

222

NetworkError(const std::string& message, int error_code)

223

: std::runtime_error(message), error_code_(error_code) {}

224

225

int error_code() const { return error_code_; }

226

227

private:

228

int error_code_;

229

};

230

231

// Function that throws custom exception

232

void connect_to_server(const std::string& address) {

233

// Simulate network error

234

throw NetworkError("Connection failed to " + address, 404);

235

}

236

237

PYBIND11_MODULE(example, m) {

238

// Register custom exception

239

py::register_exception<NetworkError>(m, "NetworkError");

240

241

m.def("connect_to_server", &connect_to_server);

242

}

243

244

// Python usage:

245

// try:

246

// connect_to_server("example.com")

247

// except NetworkError as e:

248

// print(f"Network error: {e}")

249

```

250

251

### Exception Translation with Custom Behavior

252

253

```cpp

254

#include <pybind11/pybind11.h>

255

256

namespace py = pybind11;

257

258

// Custom exception with additional data

259

class ValidationError : public std::exception {

260

public:

261

ValidationError(const std::string& field, const std::string& message)

262

: field_(field), message_(message) {}

263

264

const char* what() const noexcept override { return message_.c_str(); }

265

const std::string& field() const { return field_; }

266

const std::string& message() const { return message_; }

267

268

private:

269

std::string field_;

270

std::string message_;

271

};

272

273

void validate_data(const std::string& email) {

274

if (email.find('@') == std::string::npos) {

275

throw ValidationError("email", "Invalid email format");

276

}

277

}

278

279

PYBIND11_MODULE(example, m) {

280

// Register with custom translator

281

auto validation_error = py::register_exception<ValidationError>(m, "ValidationError");

282

283

// Set custom translator to include field information

284

validation_error.set_translator([](const ValidationError& e) {

285

PyErr_SetString(PyExc_ValueError,

286

("Validation error in field '" + e.field() + "': " + e.message()).c_str());

287

});

288

289

m.def("validate_data", &validate_data);

290

}

291

```

292

293

### Handling Python Exceptions in C++

294

295

```cpp

296

#include <pybind11/pybind11.h>

297

298

namespace py = pybind11;

299

300

void call_python_function(py::function func, py::object arg) {

301

try {

302

// Call Python function that might raise an exception

303

py::object result = func(arg);

304

std::cout << "Result: " << py::str(result) << std::endl;

305

}

306

catch (py::error_already_set &e) {

307

// Handle Python exception in C++

308

std::cout << "Python exception caught: " << e.what() << std::endl;

309

310

// Check exception type

311

if (e.matches(PyExc_ValueError)) {

312

std::cout << "It was a ValueError" << std::endl;

313

}

314

315

// Re-raise the exception to Python

316

e.restore();

317

throw;

318

}

319

}

320

321

PYBIND11_MODULE(example, m) {

322

m.def("call_python_function", &call_python_function);

323

}

324

```

325

326

### Exception Context Management

327

328

```cpp

329

#include <pybind11/pybind11.h>

330

331

namespace py = pybind11;

332

333

py::object safe_python_call(py::function func) {

334

py::error_scope scope; // Automatically manages error state

335

336

try {

337

return func();

338

}

339

catch (...) {

340

if (scope.has_error()) {

341

// Handle any Python errors that occurred

342

auto error = scope.get_error();

343

std::cout << "Error during call: " << error.what() << std::endl;

344

throw;

345

}

346

// Handle C++ exceptions

347

throw;

348

}

349

}

350

351

PYBIND11_MODULE(example, m) {

352

m.def("safe_python_call", &safe_python_call);

353

}

354

```

355

356

### Iterator Exception Handling

357

358

```cpp

359

#include <pybind11/pybind11.h>

360

361

namespace py = pybind11;

362

363

class NumberIterator {

364

int current_, max_;

365

public:

366

NumberIterator(int max) : current_(0), max_(max) {}

367

368

NumberIterator& iter() { return *this; }

369

370

int next() {

371

if (current_ >= max_) {

372

// Proper way to signal iteration end

373

throw py::stop_iteration();

374

}

375

return current_++;

376

}

377

};

378

379

PYBIND11_MODULE(example, m) {

380

py::class_<NumberIterator>(m, "NumberIterator")

381

.def(py::init<int>())

382

.def("__iter__", &NumberIterator::iter,

383

py::return_value_policy::reference_internal)

384

.def("__next__", &NumberIterator::next);

385

}

386

```

387

388

### Exception Chaining

389

390

```cpp

391

#include <pybind11/pybind11.h>

392

393

namespace py = pybind11;

394

395

void process_file(const std::string& filename) {

396

try {

397

// Simulate file processing that might fail

398

if (filename.empty()) {

399

throw std::invalid_argument("Filename cannot be empty");

400

}

401

402

// Simulate I/O error

403

throw std::runtime_error("File not found: " + filename);

404

}

405

catch (const std::invalid_argument& e) {

406

// Chain exceptions

407

throw std::runtime_error("Failed to process file: " + std::string(e.what()));

408

}

409

}

410

411

PYBIND11_MODULE(example, m) {

412

m.def("process_file", &process_file);

413

}

414

```

415

416

## Error Handling Best Practices

417

418

### Resource Management with Exceptions

419

420

```cpp

421

#include <pybind11/pybind11.h>

422

#include <memory>

423

424

namespace py = pybind11;

425

426

class Resource {

427

public:

428

Resource() { /* acquire resource */ }

429

~Resource() { /* release resource */ }

430

431

void use() {

432

// Might throw an exception

433

throw std::runtime_error("Resource error");

434

}

435

};

436

437

void use_resource() {

438

// Use RAII for exception safety

439

auto resource = std::make_unique<Resource>();

440

441

try {

442

resource->use();

443

}

444

catch (...) {

445

// Resource automatically cleaned up by unique_ptr

446

throw;

447

}

448

}

449

450

PYBIND11_MODULE(example, m) {

451

m.def("use_resource", &use_resource);

452

}

453

```

454

455

## Types

456

457

```cpp { .api }

458

namespace pybind11 {

459

// Exception handling classes

460

class error_already_set;

461

class builtin_exception;

462

class cast_error;

463

class reference_cast_error;

464

465

// Built-in Python exception wrappers

466

class stop_iteration;

467

class index_error;

468

class key_error;

469

class value_error;

470

class type_error;

471

class attribute_error;

472

473

// Custom exception registration

474

template<typename CppException> class exception;

475

476

// Utility classes

477

class error_scope;

478

479

// Exception registration functions

480

template<typename CppException>

481

exception<CppException>& register_exception(module_ &m, const char *name, handle base);

482

483

template<typename CppException>

484

void register_exception_translator(std::function<void(const CppException&)> translator);

485

}

486

```