PyO3 / PyO3/pyo3

`BaseException`(`SystemExit`/`KeyboardInterrupt`) is swallowed and converted to a `TypeError` when extracting struct fields

Open
#5,457 5 comments 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Rust
Stars
16.2k
Forks
1k
Avg merge
2d 6h
Merged PRs (30d)
66

Description

Bug Description

Opening as a bug, but this might be considered a feature request

First - thank you for such a great library
We're using it to speedup some python in a web service running under gunicorn and hit a case where a SystemExit is swallowed and converted to a TypeError if it happened to be raised inside a field extractor in a struct

I believe this code is acting as a bare except: but IMO should be more like except Exception:
https://github.com/PyO3/pyo3/blob/ae64e57330427e5ef969f4637c59222d25b1d840/src/impl_/frompyobject.rs#L45-L62

This swallows exceptions deriving from BaseException like KeyboardInterrupt (user pressing Ctrl+C) and SystemExit (used by gunicorn to signal worker shutdown - https://github.com/benoitc/gunicorn/blob/a86ea1e4e6c271d1cd1823c7e14490123f9238fe/gunicorn/workers/base.py#L204

Steps to Reproduce

Seems to only happen with nested structs, see full repro here - https://github.com/vpoverennov/pyo3-exceptions-repro/blob/main/src/lib.rs

with a Nested class like this (simulating SystemExit being thrown into an otherwise innocuous getter function)

class Nested:
    @property
    def v(self):
        raise SystemExit(1)

This works fine and SystemExit is raised when calling repro_w

#[derive(FromPyObject, Debug)]
struct Nested {
    v: i32,
}

#[pyfunction]
fn repro_n(b: Nested) -> i32 {
    println!("repro_n: {:?}", b);
    b.v
}

But this converts SystemExit into a TypeError: argument 'a': failed to extract field Wrapper.n

#[derive(FromPyObject, Debug)]
struct Wrapper {
    n: Nested,
}

#[derive(FromPyObject, Debug)]
struct Nested {
    v: i32,
}

#[pyfunction]
fn repro_w(a: Wrapper) -> i32 {
    println!("repro_w: {:?}", a);
    a.n.v
}
Backtrace

Your operating system and version

Windows 10 / MacOS

Your Python version (python --version)

Python 3.10

Your Rust version (rustc --version)

rustc 1.90.0 (1159e78c4 2025-09-14)

Your PyO3 version

0.26.0

How did you install python? Did you use a virtualenv?

not relevant

Additional Info

No response

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in src/impl_/frompyobject.rs at the field-extraction logic linked in the report, then reproduce the nested Wrapper/Nested example with a property that raises SystemExit. Done means SystemExit and KeyboardInterrupt propagate from nested field extraction instead of being converted into a TypeError.

Written by the indexing model from the issue text.

Assessment

Tech stack
python, rust
Domain
api, backend
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Clearly specified
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.