You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Rust + PyO3时遇生命周期错误E0106,求解决方案

问题分析与解决方案

错误原因

你的代码核心问题在于错误地将&Python标记为'static生命周期,并且试图从函数返回这个引用。Python实例由Python::with_gil创建,它的生命周期严格绑定到闭包作用域——闭包执行完毕后GIL(全局解释器锁)会被释放,对应的Python引用随即失效,Rust的借用检查器会阻止这种悬垂引用的产生。

另外,你在闭包中返回&py的写法也存在问题:py本身就是&Python类型,无需额外取引用,而且它的生命周期无法扩展到函数外部。

正确实现方案

方案一:让调用者管理GIL,函数接收&Python参数

这是最直接的修正方式,将GIL持有权交给调用者,函数仅负责在GIL上下文内加载模块:

use pyo3::{prelude::*, fs};

fn get_python_module(py: &Python) -> PyResult<&PyModule> {
    let indicators_file = fs::read_to_string(concat!(
        env!("CARGO_MANIFEST_DIR"),
        "/python_lib/base.py"
    ))
    .expect("Should have been able to read the file");

    PyModule::from_code(py, &indicators_file, "indicators", "indicators")
}

// 调用示例
fn main() -> PyResult<()> {
    Python::with_gil(|py| {
        let module = get_python_module(py)?;
        // 在这里使用module执行Python逻辑
        Ok(())
    })
}

方案二:封装GIL管理与模块使用逻辑

如果想把GIL管理和模块操作封装在一起,可以让函数接收一个闭包,在GIL上下文内完成所有操作:

use pyo3::{prelude::*, fs};

fn with_python_module<F, R>(f: F) -> PyResult<R>
where
    F: FnOnce(&PyModule) -> PyResult<R>,
{
    let indicators_file = fs::read_to_string(concat!(
        env!("CARGO_MANIFEST_DIR"),
        "/python_lib/base.py"
    ))
    .expect("Should have been able to read the file");

    Python::with_gil(|py| {
        let module = PyModule::from_code(py, &indicators_file, "indicators", "indicators")?;
        f(module)
    })
}

// 调用示例
fn main() -> PyResult<()> {
    with_python_module(|module| {
        // 调用Python模块中的函数
        module.call0("your_python_function")?;
        Ok(())
    })
}

方案三:全局静态模块(复用场景)

如果需要多次复用同一个Python模块,避免重复加载,可以使用once_cell创建全局静态模块:

use pyo3::{prelude::*, fs, types::PyModule};
use once_cell::sync::OnceCell;

// 全局静态存储模块,只初始化一次
static INDICATORS_MODULE: OnceCell<Py<PyModule>> = OnceCell::new();

fn get_static_python_module() -> PyResult<&'static Py<PyModule>> {
    INDICATORS_MODULE.get_or_try_init(|| {
        let indicators_file = fs::read_to_string(concat!(
            env!("CARGO_MANIFEST_DIR"),
            "/python_lib/base.py"
        ))
        .expect("Should have been able to read the file");

        Python::with_gil(|py| {
            let module = PyModule::from_code(py, &indicators_file, "indicators", "indicators")?;
            // 将模块转换为Py<T>类型,脱离当前GIL生命周期
            Ok(module.into())
        })
    })
}

// 调用示例
fn main() -> PyResult<()> {
    let module = get_static_python_module()?;
    Python::with_gil(|py| {
        // 将Py<PyModule>转换为当前GIL下的引用
        let module_ref = module.as_ref(py);
        // 使用模块
        Ok(())
    })
}

内容的提问来源于stack exchange,提问作者g992

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 02:05:34