Does PyO3 know to skip PyType conversions when it can? #4915
-
I know I could benchmark this to test it but I am not confident that I would get a definitive answer, and I thought it'd be better to ask here. I didn't see this mentioned in the docs but maybe I missed it. My question is whether there's any conversion cost to calling a PyFunction/PyMethod from another PyFunction, in PyO3 code, or is it equivalent to pure Rust? That is, if I have something like #[pymethods]
impl MyClass {
fn foo(&self, bar: usize) -> PyResult<usize> {
// ... compute something and return a PyResult<usize> ...
}
fn baz(&self, bar: usize) -> PyResult<...> {
let foo_val = self.foo(bar)? // I need a foo here
// ... do stuff with the foo
}
} Would there be any benefit to defining a Like I said above, I wasn't able to answer this from reading the docs. I think it might be a useful note to add somewhere, perhaps inside "Calling Python from Rust" or after that section. |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 1 reply
-
If you call Around your It's different if you take Python types as function parameters, e.g. |
Beta Was this translation helpful? Give feedback.
If you call
foo
frombaz
, there will be no conversion needed. It remains a Rust function that takes a usize and returns a usize or PyErr.PyResult
is simply a type alias forResult<T, PyErr>
, so in the happy case no overhead is added. In the error case, constructing a PyErr is maybe a little more heavy than other error types, but in your example you need one anyway to return frombaz
.Around your
fn foo
, PyO3 constructs a wrapper function that is exposed to the Python/C API, which takes PyObject and converts when called. But that is not used when you call the original function from Rust.It's different if you take Python types as function parameters, e.g.
fn foo(&self, bar: &PyString)
or …