Skip to content

Running in virtualenvs on Windows #1896

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

Open
davidhewitt opened this issue Oct 1, 2021 · 1 comment
Open

Running in virtualenvs on Windows #1896

davidhewitt opened this issue Oct 1, 2021 · 1 comment

Comments

@davidhewitt
Copy link
Member

See also #1835

If I create a new virtualenv on Windows, install tomli into it, and run the following program:

use pyo3::prelude::*;

fn main() -> PyResult<()>{
    Python::with_gil(|py| {
        let m = PyModule::import(py, "tomli")?;
        Ok(())
    })
}

Then this fails to import tomli, despite building correctly with the virtualenv. On linux (at least Ubuntu 20.04) the equivalent works correctly.

I suspect we could investigate how pyo3::prepare_freethreaded_python sets up the interpreter - presumably on Windows it fails to detect the virtualenv, but on Linux it's fine.

@clouds56
Copy link

I suspect we could investigate how pyo3::prepare_freethreaded_python sets up the interpreter - presumably on Windows it fails to detect the virtualenv, but on Linux it's fine.

after some investigation: running this code in both linux and windows

#[test]
pub fn test_py() {
  pyo3::prepare_freethreaded_python();
  pyo3::Python::with_gil(|py| {
    let sys = py.import("sys").unwrap();
    let version: String = sys.getattr("version").unwrap().extract().unwrap();
    println!("Python version: {}", version);

    let prefix: String = sys.getattr("prefix").unwrap().extract().unwrap();
    println!("Python prefix: {}", prefix);

    let executable: String = sys.getattr("executable").unwrap().extract().unwrap();
    println!("Python executable: {}", executable);

    let python_path = sys.getattr("path").unwrap();
    let python_path: Vec<String> = python_path.extract().unwrap();
    println!("Python path: {:?}", python_path);

    let os = py.import("os").unwrap();
    let path: String = os.getattr("getcwd").unwrap().call0().unwrap().extract().unwrap();
    println!("Current directory: {}", path);
  });
}

I found that on linux the executable resolves to "python",

Python version: 3.13.2 (main, Mar 13 2025, 14:29:07) [GCC 14.2.0]
Python prefix: /home/clouds/Projects/Hello/pyo3/.venv
Python executable: /home/clouds/Projects/Hello/pyo3/.venv/bin/python3
Python path: ["/usr/lib/python313.zip", "/usr/lib/python3.13", "/usr/lib/python3.13/lib-dynload", "/home/clouds/Projects/Hello/pyo3/.venv/lib/python3.13/site-packages"]
Current directory: /home/clouds/Projects/Hello/pyo3

while on windows the executable resolves to "test.exe"

Python version: 3.13.2 (tags/v3.13.2:4f8bb39, Feb  4 2025, 15:23:48) [MSC v.1942 64 bit (AMD64)]
Python prefix: D:\Hello\pyo3
Python executable: D:\Hello\pyo3\target\debug\deps\pyo3-c13b9e0a445d0fc6.exe
Python path: ["D:\\Hello\\pyo3\\.venv\\Scripts\\python313.zip", "C:\\Users\\clouds\\AppData\\Local\\Programs\\Python\\Python313\\Lib", "C:\\Users\\clouds\\AppData\\Local\\Programs\\Python\\Python313\\DLLs", "D:\\Hello\\pyo3", "D:\\Hello\\pyo3\\Lib", "D:\\Hello\\pyo3\\target\\debug\\deps"]
Current directory: D:\Hello\pyo3

So they resolve to different prefix.

Change initial code to things like this would work

    let output = Command::new("python").env("PYTHONIOENCODING", "utf-8").arg("-c").arg("import sys; print(sys.executable)").output()?;
    let executable = String::from_utf8(output.stdout).unwrap();
    let mut config = unsafe { std::mem::zeroed() };
    unsafe {
      ffi::PyConfig_InitIsolatedConfig(&mut config);
      ffi::PyConfig_SetString(&mut config, &mut config.executable, executable.to_wchar().as_mut_ptr());
      ffi::Py_InitializeFromConfig(&config)
    }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants