Fix PYTHONHOME inheritance when spawning different Python versions (#17821)
## Summary Fixes #17814. When a Python version installed by uv spawns another Python version via subprocess (e.g., Python 3.12 spawning Python 3.13), the child process would inherit the parent's `PYTHONHOME` environment variable. This caused the child Python to load the wrong stdlib, resulting in errors like `AssertionError: SRE module mismatch`. The fix removes the check that prevented overwriting an inherited `PYTHONHOME` value. Now the Windows trampoline always sets `PYTHONHOME` to the correct directory for non-virtualenv Python installations, ensuring each Python version uses its own stdlib. ## Test Plan Tested manually using the reproduction script from the issue: ``` uv python install 3.12 uv python install 3.13 echo "from os import environ;print(environ['PYTHONHOME']);import re" > test.py python3.12.exe -c "import subprocess; subprocess.run(['python3.13.exe', 'test.py'])" ``` Before: `AssertionError: SRE module mismatch` After: Runs successfully with correct `PYTHONHOME` pointing to 3.13's installation. --------- Co-authored-by: Zanie Blue <contact@zanie.dev>
This commit is contained in:
committed by
GitHub
parent
f1e4ecf697
commit
396ff569ca
@@ -568,6 +568,12 @@ impl EnvVars {
|
||||
#[attr_added_in("0.9.15")]
|
||||
pub const UV_INTERNAL__TEST_LFS_DISABLED: &'static str = "UV_INTERNAL__TEST_LFS_DISABLED";
|
||||
|
||||
/// Marker variable to track whether `PYTHONHOME` was set by uv.
|
||||
/// Used by the Windows trampoline to distinguish uv-set values from user-set values.
|
||||
#[attr_hidden]
|
||||
#[attr_added_in("next release")]
|
||||
pub const UV_INTERNAL__PYTHONHOME: &'static str = "UV_INTERNAL__PYTHONHOME";
|
||||
|
||||
/// Path to system-level configuration directory on Unix systems.
|
||||
#[attr_added_in("0.4.26")]
|
||||
pub const XDG_CONFIG_DIRS: &'static str = "XDG_CONFIG_DIRS";
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -146,20 +146,35 @@ fn make_child_cmdline() -> CString {
|
||||
// be correctly detected when using trampolines.
|
||||
std::env::set_var(EnvVars::PYVENV_LAUNCHER, &executable_name);
|
||||
|
||||
// If this is not a virtual environment and `PYTHONHOME` has
|
||||
// not been set, then set `PYTHONHOME` to the parent directory of
|
||||
// the executable. This ensures that the correct installation
|
||||
// directories are added to `sys.path` when running with a junction
|
||||
// trampoline.
|
||||
let python_home_set =
|
||||
std::env::var(EnvVars::PYTHONHOME).is_ok_and(|home| !home.is_empty());
|
||||
if !is_virtualenv(python_exe.as_path()) && !python_home_set {
|
||||
std::env::set_var(
|
||||
EnvVars::PYTHONHOME,
|
||||
python_exe
|
||||
// If this is not a virtual environment, set `PYTHONHOME` to
|
||||
// the parent directory of the executable. This ensures that
|
||||
// the correct installation directories are added to `sys.path`
|
||||
// when running with a junction trampoline.
|
||||
//
|
||||
// We use a marker variable (`UV_INTERNAL__PYTHONHOME`) to track
|
||||
// whether `PYTHONHOME` was set by uv. This allows us to:
|
||||
// - Override inherited `PYTHONHOME` from parent Python processes
|
||||
// - Preserve user-defined `PYTHONHOME` values
|
||||
if !is_virtualenv(python_exe.as_path()) {
|
||||
let python_home = std::env::var(EnvVars::PYTHONHOME).ok();
|
||||
let marker = std::env::var(EnvVars::UV_INTERNAL__PYTHONHOME).ok();
|
||||
|
||||
// Only set `PYTHONHOME` if:
|
||||
// - It's not set, OR
|
||||
// - It was set by uv (marker matches current `PYTHONHOME`)
|
||||
let should_override = match (&python_home, &marker) {
|
||||
(None, _) => true,
|
||||
(Some(home), Some(m)) if home == m => true,
|
||||
_ => false,
|
||||
};
|
||||
|
||||
if should_override {
|
||||
let home = python_exe
|
||||
.parent()
|
||||
.expect("Python executable should have a parent directory"),
|
||||
);
|
||||
.expect("Python executable should have a parent directory");
|
||||
std::env::set_var(EnvVars::PYTHONHOME, home);
|
||||
std::env::set_var(EnvVars::UV_INTERNAL__PYTHONHOME, home);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user