-
-
Notifications
You must be signed in to change notification settings - Fork 239
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
PyO3 support #324
Comments
👋! It should be possible for binaries created with PyOxidizer to load extensions built against PyO3. But it all comes down to how things are linked. As I'm sure you know, this can be a thorny problem space. If extensions are built in a way that is compatible with PyPI supported binary wheels, things should just work. But if we have to recompile from source to get static linking, I expect this to be a minefield. (The Python extension module building ecosystem doesn't really account for the possibility of statically linked extensions, for better or worse.) PyOxidizer's run-time component (the I was actually planning to spend a few hours looking at things and open an issue against PyO3 listing all the changes we'd need. But you seem to have beat me to it :) I'm unsure what the extensive list of changes to PyO3 I'll need is. But I do know there will be changes to One bridge that needs to be crossed at some point is better support for cross-compiling. The way that both If I had to start from scratch, I'd probably abandon the myriad of Cargo features I added to python3-sys/cpython and go with a single feature to opt in to a Hope this helps! |
What an interesting response, sorry for my slow reply! Let me respond to some pieces.
Great! I'm going to try to add a PyOxidizer example to the PyO3 repo sometime soon. Expect questions 😄
Whew I see you bumped to 1.45 - I just did the same in PyO3 - that's lucky! And awesome that you're interesting in trying out PyO3; would it be helpful if I opened some PRs to PyOxidizer to do this (no guarantees on it happening fast though 😛)? Would you want
By complete fluke I just merged these the other day (untested though as yet) PyO3/pyo3#1247
We recently added a method to PyO3's
I'd be very interested to hear more about this. It's not exactly your use case, but there's some open questions at the moment about how we configure the minimum / max python version when building portable abi3 wheels. We're dangerously close to merging a swathe of features for specifying the ABI3 version, though I am also wondering whether an environment variable would be a better idea... As another thought, I've been wondering about splitting PyO3's |
I would almost certainly migrate to If you want to submit some PRs, I won't stop you. But there's a lot of code that needs changed and I likely won't merge/push anything to the I think a good place to start would be getting the various
\o/
The
ABI compatibility is probably special enough to warrant its own feature flags. But there's a raft of low-level and niche features where I think it is better to define everything via an out-of-band machine readable file.
Possibly? But a lot of that logic entails running a Python interpreter to derive interpreter features. PyOxidizer already knows these features because they are statically defined in the special Python distributions produced by https://github.com/indygreg/python-build-standalone. That's why I'd prefer a build mode for FWIW it is possible to override a build script (https://doc.rust-lang.org/cargo/reference/build-scripts.html#overriding-build-scripts). For reasons I can't recall, I didn't pursue this path with PyOxidizer. Possibly because I need something more dynamic and having to maintain per-target boilerplate doesn't scale well? I really wish Cargo would let me define an alternative build script for a given crate or the path to an output file containing |
Another reason to switch to PyO3: dgrunwald/rust-cpython#246 |
Just as a follow-up: I still would very much like to help out with this, however I unexpectedly became extremely busy just before Christmas. I'm starved of time as it is just with PyO3 maintenance, so the reality is that I won't find time to actively carry out a downstream port myself any time soon. If things free up in the future I'll do my best to come along and help out, though just wanted to let you know in case you were waiting for me to think about this ticket. |
FWIW I've been porting https://github.com/indygreg/python-zstandard to Rust using PyO3. (Not all work has been pushed yet.) Since putting in that work, I feel like I now have a good understanding of PyO3 and its differences from rust-cpython! I do find PyO3's interface to be much more pleasant! I'm not sure when I'll get around to hacking on PyOxidizer or its PyO3 port. But it is definitely something I want to pursue after the next major release. (I am anticipating having to send PRs to PyO3 for missing functionality and I don't want to be blocked on releasing PyOxidizer due to waiting on a PyO3 release with the needed missing features.) |
👍 FWIW I intend to push a PR in the not too distant future to allow PyO3's build to be configured by a file (probably JSON) - I'll be sure to cc you when that happens to make sure that we capture everything that you might need. |
I just released PyOxidizer 0.11. That means PyOxidizer can track a fork of PyO3 if needed without having to worry about it pushing back the next release by much. I've also started a local branch to begin the port to PyO3. Should I keep a running list of issues here or would you prefer I do it in PyO3's issue tracker? If the latter, would you prefer a single issue or separate issues per topic? Some proposed changes I imagine will be a bit controversial and I'd prefer to get the blessing of a PyO3 maintainer before I code up any PRs. The first major thing I found was various structs in |
More importantly, there are two different defaults, the Python configuration and the isolated configuration. The in-development docs show defaults for all the fields (some of which are not zero!), but some of them, such as Instead you could achieve nearly the same convenience as a |
The The correct way to initialize these data structures is the |
As I said above, I'm concerned that using use std::mem::MaybeUninit;
impl PyPreConfig {
/// Create a new instance initialized with the [Python configuration].
///
/// [Python configuration]: https://docs.python.org/3/c-api/init_config.html#init-python-config
fn python() -> Self {
let mut ppc = MaybeUninit::uninit();
unsafe {
PyPreConfig_InitPythonConfig(ppc.as_mut_ptr());
ppc.assume_init()
}
}
/// Create a new instance initialized with the [isolated configuration].
///
/// [isolated configuration]: https://docs.python.org/3/c-api/init_config.html#isolated-configuration
fn isolated() -> Self {
let mut ppc = MaybeUninit::uninit();
unsafe {
PyPreConfig_InitIsolatedConfig(ppc.as_mut_ptr());
ppc.assume_init()
}
}
} |
So, I was hoping to be able to incrementally port the code, using microcommits that still compiled and passed the test suite. My initial work was promising albeit ugly (there were lots of marshaling of The crux of the problem is that the cpython crate has a I don't believe there is any way I can perform a working incremental port without hacking up the GIL behavior of cpython and/or pyo3. I think Python will let you do things without the GIL held (I don't believe CPython actually validates the GIL is held as much as you think it would). So I'm leaning towards running a fork of @davidhewitt I assume you've seen this story play out before. Do you have any recommendations? |
Thanks for the discussion - sorry it's taken me a couple days to reply. R.e. tracking the port here or in PyO3, I'd suggest tracking the list of changes to PyO3 which PyOxidizer needs in this issue (or a similar one in PyOxidizer) because it's relevant primarily to PyOxidizer rather than PyO3. However that list of changes should probably link to various relevant issues on the PyO3 bug tracker. For example the discussion above about ... with the above in mind, I'm going to open an issue on the PyO3 bug tracker shortly linking back to this discussion and we can narrow down a desirable design for @indygreg regarding the I've seen codebases before in the process of migration which didn't have any such compatibility issue. So I'd be very happy to help debug whatever is occurring here. |
... created PyO3/pyo3#1474 |
Created PyO3/pyo3#1475 for ffi definitions for missing import functionality. |
I just pushed a Known issues:
I still have yet to remove the cpython crate dependency and get PyO3 building with a custom config file. Aspects of this may require some new upstream features in PyO3. I won't know until I try. But just getting pyembed to build and pass most tests with PyO3 is a huge milestone and hopefully indicates we're near the finish line! FWIW the porting process was pretty straightforward, albeit a bit laborious. I did lose an hour or two to debugging a crash related to GILPool attempting to decref some pointers after the interpreter was finalized. I fixed this by ensuring our held |
Awesome progress! I think you're exercising some less-commonly-used parts of PyO3 - which is great, however I must apologize for the teething problems 😬 I'd love to review the pyo3 branch when it's ready to be put forward as a full PR. I can offer anything I consider idiomatic potentially missed during the porting process. Similarly I can help figure out any config file changes needed. R.E. performance - I'd hope we're similar to |
It looks like the PyO3 issues originally linked have been fixed. What does the integration look like currently? |
A PyO3 maintainer here unfamiliar with PyOxidizer, just discovered it this afternoon. 👋
Looks like a really cool project! We reasonably often have pain with users who want to embed Python in Rust programs; there's all kinds of subtleties around static linking etc. So it'd be great to understand a little bit about what would be necessary for PyOxidizer to work with PyO3 projects (if it doesn't already).
I'd be very happy to help out with any implementation work needed and also add some notes to the PyO3 guide / add an example in the PyO3 repo.
Also, while reading your docs I noticed this section: https://pyoxidizer.readthedocs.io/en/stable/status.html?highlight=pyo3#pyo3
I'd be very happy to answer any questions you have about using PyO3 in
pyembed
& help with the implementation if you're interested in switching. IMO helping with downstream usage from time to time gives me ideas how to improve the ergonomics in PyO3!The text was updated successfully, but these errors were encountered: