PyO3's attributes (
#[pymodule], etc.) are procedural macros, which means that they rewrite the source of the annotated item. You can view the generated source with the following command, which also expands a few other things:
cargo rustc --profile=check -- -Z unstable-options --pretty=expanded > expanded.rs; rustfmt expanded.rs
(You might need to install rustfmt if you don't already have it.)
You can also debug classic
!-macros by adding
cargo rustc --profile=check -- -Z unstable-options --pretty=expanded -Z trace-macros > expanded.rs; rustfmt expanded.rs
See cargo expand for a more elaborate version of those commands.
Running with Valgrind
Valgrind is a tool to detect memory management bugs such as memory leaks.
You first need to install a debug build of Python, otherwise Valgrind won't produce usable results. In Ubuntu there's e.g. a
Activate an environment with the debug interpreter and recompile. If you're on Linux, use
ldd with the name of your binary and check that you're linking e.g.
libpython3.7d.so.1.0 instead of
Download the suppressions file for CPython.
Run Valgrind with
valgrind --suppressions=valgrind-python.supp ./my-command --with-options
Getting a stacktrace
The best start to investigate a crash such as an segmentation fault is a backtrace. You can set
RUST_BACKTRACE=1 as an environment variable to get the stack trace on a
panic!. Alternatively you can use a debugger such as
gdb to explore the issue. Rust provides a wrapper,
rust-gdb, which has pretty-printers for inspecting Rust variables. Since PyO3 uses
cdylib for Python shared objects, it does not receive the pretty-print debug hooks in
rust-gdb (rust-lang/rust#96365). The mentioned issue contains a workaround for enabling pretty-printers in this case.
- Link against a debug build of python as described in the previous chapter
- Set a breakpoint (
rust_panicif you are investigating a
- After the crash occurred, enter
bt fullto print the stacktrace
Often it is helpful to run a small piece of Python code to exercise a section of Rust.
rust-gdb --args python -c "import my_package; my_package.sum_to_string(1, 2)"