-
Notifications
You must be signed in to change notification settings - Fork 803
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
Implement ToPyObject
for bytes::Bytes
#1992
Comments
Only if the slice has a static lifetime. Otherwise the slice has to be copied regardless. |
This would be very welcome IMO! I've wondered about adding an optional |
Oh, hm, yeah you're right: https://docs.rs/bytes/1.1.0/bytes/struct.Bytes.html#method.copy_from_slice Good point. We can possibly change that internal API to return
Sweet! Thanks. |
I don't think we need anything new for this. Converting use pyo3::prelude::*;
use pyo3::types::PyBytes;
use bytes::Bytes;
fn main() {
let bytes = Bytes::from_static(&[1,2,3,4]);
Python::with_gil(|py|{
let pb = PyBytes::new(py, &bytes);
dbg!(pb);
})
} Looking at the capi and Bytes' implementation it doesn't look like we can do something clever here. |
|
That is true, and it would be more convenient. But it has some footgunny behavior - I can totally see someone starting with a I don't think it would be a disaster or anything, but I think it would be a mistake to offer this api if we can't implement it in a clever way. Perhaps this is best offered in a container-agnostic way, like |
I believe
Implementations like this are possible, though I kinda don't like them because I think each Rust type should map to only one Python type. In the future I would like to remove the generic parameter from |
It goes through a boxed slice, which can reallocate if there is excess capacity. |
Ah interesting, I wasn't aware of that. I guess that's one of those impossible API questions where different users want different things 🤷 EDIT: actually thinking about it, not reallocating and continuing to hold the extra capacity is a perf optimization that would confuse a lot of users seeing excess memory consumption, so |
I'm thinking the best way to do this is to create an object that wraps a |
That would be very efficient! Because of the complexity of #1444 I shy away from utility pyclasses in libraries at the moment. It's definitely something we need to figure out, however at the moment each extension module would get its own copy of such a type and they wouldn't compare equal etc. |
(However we could create an example for users to adapt in their own code? Also in #1884 I hope to offer a safe way to implement buffer protocol using |
An example sounds totally reasonable to me! I definitely would not want adding this convenience to impede future foundational improvements to PyO3. |
The
bytes
crate from Tokio is really useful for operating on bytes in a performant way: https://docs.rs/crate/bytes/1.1.0.We use it in Pants. I'd love to convert a
#[pyfunction]
we have to be able to stop acquiring the GIL inside of a future so that we can better usepy.allow_threads(||)
. But lifetimes mean that we only have access to&[u8]
in the future, so we would need to convert intoVec<u8>
, which is more copying than we can tolerate, especially because iirc thatVec<u8>
would then get copied again into thePyBytes
?. https://github.com/pantsbuild/pants/blob/d62a3cd87c114e379748edbfa279f6fa11da6fd5/src/rust/engine/src/externs/interface.rs#L1399Instead, I think I'm hoping to have that future convert the
&[u8]
intoBytes
(which does zero copying). And then PyO3 will convertBytes
intoPyBytes
automatically outside of my#[pyfunction]
- allowing me to usepy.allow_threads()
the whole time. Does that make sense?I imagine this would be a new Cargo feature.
I'm very happy to contribute this!
The text was updated successfully, but these errors were encountered: