diff --git a/src/virtualenv/discovery/py_info.py b/src/virtualenv/discovery/py_info.py index 7c680eeaa..d9f9fce2d 100644 --- a/src/virtualenv/discovery/py_info.py +++ b/src/virtualenv/discovery/py_info.py @@ -138,6 +138,20 @@ def _fast_get_system_executable(self): base_executable = getattr(sys, "_base_executable", None) # some platforms may set this to help us if base_executable is not None: # use the saved system executable if present if sys.executable != base_executable: # we know we're in a virtual environment, cannot be us + # Do light validation for non-Windows virtual environments + # Some installs/distributions do not provide a version-less "python" binary (PEP 394). + # Try to fallback to an alternative based on version number + # This should still be relatively fast since it's just a couple of `stat` calls + if self.os != "nt" and (self.version_info.major, self.version_info.minor) >= (3, 11): + if not os.path.exists(base_executable): + major, minor = self.version_info.major, self.version_info.minor + base_dir = os.path.dirname(base_executable) + for candidate in [ + os.path.join(base_dir, f"python{v}") for v in (major, f"{major}.{minor}") + ]: + if os.path.exists(candidate): + base_executable = candidate + break return base_executable return None # in this case we just can't tell easily without poking around FS and calling them, bail # if we're not in a virtual environment, this is already a system python, so return the original executable