使用Virtualenv结合PyO3时遭遇ModuleNotFoundError(pyarrow缺失)
解决PyO3无法识别虚拟环境Python依赖的问题
问题背景
在Rust项目中结合Virtualenv/pyenv虚拟环境使用PyO3时,PyO3始终调用系统Python而非虚拟环境,导致pyarrow等依赖找不到——即使已在虚拟环境中安装对应包。相关代码与依赖如下:
代码与依赖
main.rs
use polars::prelude::*; use pyo3::{prelude::*, types::PyModule}; use pyo3_polars::PyDataFrame; fn main() -> PyResult<()> { let code = include_str!("./test.py"); Python::with_gil(|py| { let activators = PyModule::from_code(py, code, "activators.py", "activators")?; let df: DataFrame = df!( "integer" => &[1, 2, 3, 4, 5], "float" => &[4.0, 5.0, 6.0, 7.0, 8.0], ) .unwrap(); let relu_result: PyDataFrame = activators .getattr("test")? .call1((PyDataFrame { 0: df },))? .extract()?; Ok(()) }) }
test.py
def test(x): import pyarrow import sys print(sys.executable, sys.path) # manipulate dataframe x return x
Cargo.toml
[dependencies] pyo3 = { version = "0.20.0", features = ["auto-initialize"] } polars = "0.35.4" pyo3-polars = "0.9.0"
问题现象
- 激活虚拟环境后执行
cargo run,报错ModuleNotFoundError: No module named 'pyarrow' - 注释
import pyarrow后,错误仍来自pyo3-polars的类型转换逻辑,且输出显示PyO3使用系统Python路径 - 切换到pyenv虚拟环境后问题依旧
解决方案
PyO3的auto-initialize特性会自动查找系统Python,要让它绑定虚拟环境的Python,可通过以下两种方式解决:
方式1:环境变量指定(推荐)
激活虚拟环境后,设置PYO3_PYTHON环境变量指向虚拟环境的Python可执行文件,再运行项目:
# 激活Virtualenv环境 . venv/bin/activate # 绑定虚拟环境Python路径 export PYO3_PYTHON="$VIRTUAL_ENV/bin/python3" # 运行项目 cargo run
对于pyenv环境:
pyenv activate your-env-name # 绑定pyenv环境的Python路径 export PYO3_PYTHON="$(pyenv which python)" cargo run
方式2:手动初始化Python解释器
修改Cargo.toml移除auto-initialize特性:
pyo3 = { version = "0.20.0", features = [] }
在Rust代码中手动指定Python路径并初始化:
use polars::prelude::*; use pyo3::{prelude::*, types::PyModule}; use pyo3_polars::PyDataFrame; use pyo3::ffi::Py_SetProgramName; use std::ffi::CString; fn main() -> PyResult<()> { // 替换为你的虚拟环境Python路径 let python_path = "/path/to/your/venv/bin/python3"; let c_path = CString::new(python_path).unwrap(); unsafe { Py_SetProgramName(c_path.as_ptr()); } Python::with_gil(|py| { // 将虚拟环境的site-packages加入Python路径 let sys = py.import("sys")?; let venv_site_packages = "/path/to/your/venv/lib/python3.x/site-packages"; // 替换为对应路径 sys.call_method1("append", (venv_site_packages,))?; let code = include_str!("./test.py"); let activators = PyModule::from_code(py, code, "activators.py", "activators")?; let df: DataFrame = df!( "integer" => &[1, 2, 3, 4, 5], "float" => &[4.0, 5.0, 6.0, 7.0, 8.0], ) .unwrap(); let relu_result: PyDataFrame = activators .getattr("test")? .call1((PyDataFrame { 0: df },))? .extract()?; Ok(()) }) }
验证生效
修改test.py添加验证输出:
def test(x): import sys print("当前Python路径:", sys.executable) import pyarrow print("PyArrow版本:", pyarrow.__version__) return x
运行后若输出虚拟环境的Python路径及PyArrow版本,说明问题解决。
内容的提问来源于stack exchange,提问作者JACK M
相关产品推荐
相关产品推荐

