-
Notifications
You must be signed in to change notification settings - Fork 776
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
ModuleNotFoundError: No module named 'supermodule.submodule'; 'supermodule' is not a package #759
Comments
This is unfortunately a flaw in the way Python imports modules from native extensions. I think if you run |
I've run into this same issue with version 0.8.5 on Mac and no combination of imports that I've tried has worked, including the above suggestion. |
Thanks for the note. I must have mis-remembered that. Based on stack overflow the solution looks like you might be able to create a symlink to the main library which has the name of the submodule: https://stackoverflow.com/questions/48706842/python-3-x-c-extension-module-and-submodule |
You can fix this in a somewhat hacky way by adding the module to #[pymodule]
fn supermodule(py: Python, module: &PyModule) -> PyResult<()> {
module.add_wrapped(wrap_pymodule!(submodule))?;
py.run("\
import sys
sys.modules['supermodule.submodule'] = submodule
", None, Some(module.dict()))?;
Ok(())
} The documentation claims that After a lot of trial and error, I am fairly convinced that the only "fully robust" solution that will also make static analysis tools happy is to have your entire module hierarchy represented in the file system. Whether you do this with Python files or with separate extension modules is up to you. I agree with the comments in PyO3/maturin#266 that we should look into how numpy, pandas, etc. handle this and see if there is a better way. It would be great if in the meantime PyO3 could emit code to modify |
A solution for this came up in #1517 (comment) We could try to support this pattern internally in PyO3 (or at least add documentation). |
Somewhat unrelated but maybe this will help someone. In my particular case I had a module on-disk with a number of submodules. I only wanted to import a subset of the submodules. Tried many solutions (e.g.
|
For the record, an alternative to the #[pymodule]
fn supermodule(py: Python, m: &PyModule) -> PyResult<()> {
module.add_wrapped(wrap_pymodule!(submodule))?;
py.import("sys")?
.getattr("modules")?
.set_item("supermodule.submodule", submodule)?;
Ok(())
} |
NB it looks like submodules may also have complexity with things like pickling: #2469 (comment) |
The modern incantation to do this is something like: #[pymodule]
fn supermodule(py: Python, m: &PyModule) -> PyResult<()> {
let submodule = pyo3::wrap_pymodule!(submodule);
m.add_wrapped(submodule)?;
py.import("sys")?
.getattr("modules")?
.set_item("supermodule.submodule", submodule(py))?;
Ok(())
} |
I'm encountering this same issue and when using the solution suggested in #759 (comment) (via copy/paste). After
I don't see any issues in this repo on this particular error (multiple initialization) - any idea where I've gone wrong? (I see from https://github.com/PyO3/pyo3/blob/7bdc504252a2f972ba3490c44249b202a4ce6180/guide/src/migration.md#each-pymodule-can-now-only-be-initialized-once-per-process that this is new behavior as of the 28 August release of 0.17 but it's not clear from that writeup what 'the ability to initialize a #[pymodule] more than once in the same process' means - i.e. I am just starting a REPL and importing the package one time to trigger the error). |
If I back down to pyo3 v0.16.6, the import works without error so it's something new to 0.17.x. |
@jdiggans-twist I've created a separate issue #2644 to discuss. |
One addition: the Here is the complete solution I use for this: #[pymodule]
fn supermodule(py: Python, m: &PyModule) -> PyResult<()> {
let submodule = create_my_submodule()?; // function that creates the &PyModule
m.add_submodule(submodule)?;
py.import("sys")?
.getattr("modules")?
.set_item("supermodule.submodule", submodule)?;
// needs to be set *after* `add_submodule()`
submodule.setattr("__name__", "supermodule.submodule")?;
Ok(())
} |
Here is my solution that correctly sets #[pymodule]
fn supermodule(py: Python, m: &PyModule) -> PyResult<()> {
let child_module = PyModule::new(py, "supermodule.submodule")?;
submodule(py, child_module)?;
m.add("submodule", child_module)?;
py.import("sys")?.getattr("modules")?.set_item("supermodule.submodule", child_module)?;
Ok(())
} |
Hi guys, I was able to use all the above to get submodules going for my package. Thank you! Something I couldn't figure out was adding type stubs to the package after this. I followed the tutorial, but it seems highly specific to modules that don't have submodules. Is there a way to add type's to projects that include submodules without creating the python source folder? Thanks! |
@nleroy917 maybe #3591 (reply in thread) helps you? |
@davidhewitt Thank you for pointing me there, that seems to be the exact problem I was having. In the meantime, I got something working after reading this in the documentation:
It's not perfect, and I am repeating myself a lot, but it works and is sufficient for now. I sincerely appreciate your work on this project! It's become an indispensable tool in my workflow |
FYI: The workaround posted in #759 (comment) also works for the experimental declarative API (which is awesome, btw!) #[pymodule]
mod my_module {
use super::*;
#[pymodule]
mod my_submodule {
use super::*;
/// Hack: workaround for https://github.com/PyO3/pyo3/issues/759
#[pymodule_init]
fn init(m: &Bound<'_, PyModule>) -> PyResult<()> {
Python::with_gil(|py| {
py.import_bound("sys")?
.getattr("modules")?
.set_item("my_module.my_submodule", m)
})
}
}
} |
🐛 Bug Reports
I am working for writing Python extension, but facing import submodule error.
What do I expected
Import submodule like usual Python package.
🌍 Environment
ArchWSL version 19.11.16.0 on Windows Subsystem Linux 2 version Windows Insiders Slow ring 10.0.19041
rustc --version
):version = "0.x.y"
withgit = "https://github.com/PyO3/pyo3")?
Yes.
💥 Reproducing
Please provide a minimal working example. This means both the rust code and the python.
Please also write what exact flags are required to reproduce your results.
src/lib.rs
Cargo.toml
The text was updated successfully, but these errors were encountered: