使用cpython crate导入Python模块时出现ModuleNotFoundError

时间:2018-07-18 19:32:54

标签: rust cpython

我写了Rust代码:

myapp/src/main.rs

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();
}

并将Python模块保存为myapp/pyth/fibo.py

filesystem layout

但是我得到了错误:

thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: PyErr { ptype: <class 'ModuleNotFoundError'>, pvalue: Some(ModuleNotFoundError("No module named 'fibo'",)), ptraceback: None }', libcore/result.rs:945:5

我希望了解有关目录pyth的部分代码是:let module = cpython::PyModule::import(py, "fibo").unwrap();

2 个答案:

答案 0 :(得分:1)

如果您想将fibo.py与可执行文件分开保存,则有两种解决方案:

您可以将pyth文件夹添加到Python路径:

let sys = py.import("sys")?;
PyList::downcast_from(py, sys.get("path")?)?.insert_item(py, 0, "pyth");
let module = py.import("fibo")?;

这假定Rust可执行文件是从父文件夹或项目运行的,这意味着pyth是当前路径的子文件夹。

或者您可以导入pyth.fibo,就像在Python中那样:

let module = py.import("pyth.fibo")?;

这假定pyth在Python路径中(如果需要将父文件夹添加到路径中,请参阅第一个解决方案)。

答案 1 :(得分:0)

我找到了解决方法。

main.rs

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)
}

fibo.py

def fib(n):   # return Fibonacci series up to n
    print('Hello from python!')
    result = []
    a, b = 0, 1
    while a < n:
        result.append(a)
        a, b = b, a+b
    return result
相关问题