Rust 使用cpython板条箱导入Python模块时发生ModuleNotFoundError
我写了防锈代码: myapp/src/main.rs 并将Python模块保存为myapp/pyth/fibo.py 但我得到了一个错误: 线程“main”在“Err”值上调用“Result::unwrap”时惊慌失措:PyErr{ptype:,pvvalue:SomeModuleNotFoundErrorNo名为“fibo”的模块,ptraceback:None},libcore/Result.rs:945:5 我希望知道的关于目录pyth的代码部分是:let module=cpython::PyModule::importpy,fibo.unwrap 我找到了解决办法 梅因Rust 使用cpython板条箱导入Python模块时发生ModuleNotFoundError,rust,cpython,Rust,Cpython,我写了防锈代码: myapp/src/main.rs 并将Python模块保存为myapp/pyth/fibo.py 但我得到了一个错误: 线程“main”在“Err”值上调用“Result::unwrap”时惊慌失措:PyErr{ptype:,pvvalue:SomeModuleNotFoundErrorNo名为“fibo”的模块,ptraceback:None},libcore/Result.rs:945:5 我希望知道的关于目录pyth的代码部分是:let module=cpython::
如果希望将fibo.py作为独立于可执行文件的文件保存,我看到两种解决方案: 您可以将pyth文件夹添加到Python路径: 这假设Rust可执行文件是从父文件夹或项目运行的,这意味着pyth是当前路径的子文件夹 或者可以导入pyth.fibo,就像在Python中一样:
这假设pyth位于Python路径的某个位置,如果需要将父文件夹添加到该路径,请参见第一个解决方案。您希望了解目录pyth的代码的哪部分?@Shepmaster,这部分:let module=cpython::PyModule::importpy,fibo.unwrap;对不起,我想我没有把问题说清楚。为什么cpython::PyModule::import会知道名为pyth的目录?如果你叫它pyt或者pytho或者我把我的代码放在这里呢?pyth是某种特殊的硬编码目录吗?如果是这样的话,你能指出一些描述它的文档吗?@Shepmaster,嗯,我只需要它来运行模块fibo.py,所以我认为最好将它放在一个单独的文件夹中,仅此而已:请注意,这个解决方案将在你的可执行文件中嵌入Python代码,因此,每次Python代码更改时,您都需要重新编译Rust可执行文件。请参阅我的答案,了解保持Python文件独立的解决方案
extern crate cpython;
use cpython::Python;
fn main() {
let gil = Python::acquire_gil();
println!("Hello from Rust!");
let py = gil.python();
let module = cpython::PyModule::import(py, "fibo").unwrap();
module.call(py, "fib", (1,), None).unwrap();
}
extern crate cpython;
use cpython::{PyModule, PyResult, Python};
const FIBO_PY: &'static str = include_str!("../pyth/fibo.py");
fn main() {
let gil = Python::acquire_gil();
let py = gil.python();
example(py).unwrap();
}
fn example(py: Python<'_>) -> PyResult<()> {
let m = module_from_str(py, "fibo", FIBO_PY)?;
let out: Vec<i32> = m.call(py, "fib", (2,), None)?.extract(py)?;
println!(
"successfully found fibo.py at compiletime. Output: {:?}",
out
);
Ok(())
}
/// Import a module from the given file contents.
///
/// This is a wrapper around `PyModule::new` and `Python::run` which simulates
/// the behavior of the builtin function `exec`. `name` will be used as the
/// module's `__name__`, but is not otherwise important (it does not need
/// to match the file's name).
fn module_from_str(py: Python<'_>, name: &str, source: &str) -> PyResult<PyModule> {
let m = PyModule::new(py, name)?;
let builtins = cpython::PyModule::import(py, "builtins").unwrap();
m.dict(py).set_item(py, "__builtins__", &builtins).unwrap();
// OR
m.add(py, "__builtins__", py.import("builtins")?)?;
let m_locals = m.get(py, "__dict__")?.extract(py)?;
// To avoid multiple import, and to add entry to the cache in `sys.modules`.
let sys = cpython::PyModule::import(py, "sys").unwrap();
sys.get(py, "modules").unwrap().set_item(py, name, &m).unwrap();
// Finally, run the moduke
py.run(source, Some(&m_locals), None)?;
Ok(m)
}
let sys = py.import("sys")?;
PyList::downcast_from(py, sys.get("path")?)?.insert_item(py, 0, "pyth");
let module = py.import("fibo")?;
let module = py.import("pyth.fibo")?;