diff --git a/Misc/NEWS.d/next/Core and Builtins/2024-12-04-20-00-15.gh-issue-125873.58MZfl.rst b/Misc/NEWS.d/next/Core and Builtins/2024-12-04-20-00-15.gh-issue-125873.58MZfl.rst new file mode 100644 index 00000000000000..20a64450f1d7b1 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2024-12-04-20-00-15.gh-issue-125873.58MZfl.rst @@ -0,0 +1,2 @@ +We now error out early when unable to find the standard library path(s) +during ref:`Python Path initialization `. diff --git a/Modules/getpath.c b/Modules/getpath.c index 18ddfaf8dbce1a..791cf64f5de1f1 100644 --- a/Modules/getpath.c +++ b/Modules/getpath.c @@ -977,6 +977,12 @@ _PyConfig_InitPathConfig(PyConfig *config, int compute_path_config) } Py_DECREF(r); + if (PyDict_GetItemString(configDict, "_error") != NULL) { + Py_DECREF(dict); + PySys_WriteStdout("\n"); + return PyStatus_Error("error evaluating path"); + } + if (_PyConfig_FromDict(config, configDict) < 0) { PyErr_FormatUnraisable("Exception ignored in reading getpath results"); Py_DECREF(dict); diff --git a/Modules/getpath.py b/Modules/getpath.py index 7949fd813d0d07..3386a5f8d1af6a 100644 --- a/Modules/getpath.py +++ b/Modules/getpath.py @@ -677,18 +677,23 @@ def search_up(prefix, *landmarks, test=isfile): pythonpath.append(abspath(p)) # Then add the default zip file + posix_zip_builddir_quirk = False if os_name == 'nt': # QUIRK: Windows uses the library directory rather than the prefix if library: library_dir = dirname(library) else: library_dir = executable_dir - pythonpath.append(joinpath(library_dir, ZIP_LANDMARK)) + stdlib_zip = joinpath(library_dir, ZIP_LANDMARK) elif build_prefix: # QUIRK: POSIX uses the default prefix when in the build directory - pythonpath.append(joinpath(PREFIX, ZIP_LANDMARK)) + # XXX: This can lead to a ZIP file from a different installation/build + # to be present in sys.path. We should reconsider this quirk. + stdlib_zip = joinpath(PREFIX, ZIP_LANDMARK) + posix_zip_builddir_quirk = True else: - pythonpath.append(joinpath(base_prefix, ZIP_LANDMARK)) + stdlib_zip = joinpath(base_prefix, ZIP_LANDMARK) + pythonpath.append(stdlib_zip) if os_name == 'nt' and use_environment and winreg: # QUIRK: Windows also lists paths in the registry. Paths are stored @@ -749,6 +754,24 @@ def search_up(prefix, *landmarks, test=isfile): if platstdlib_dir: pythonpath.append(platstdlib_dir) + # GH-125873: Error out early if we fail to find the standard library. + missing_stdlib = False + if posix_zip_builddir_quirk or not isfile(stdlib_zip): + if not stdlib_dir or not isdir(stdlib_dir): + warn(f'Failed to find the standard library directory ({stdlib_dir=}, {stdlib_zip=})') + config['_error'] = missing_stdlib = True + # Allow platstdlib_dir to be missing in source builds for bootstraping purposes. + if not build_prefix and (not platstdlib_dir or not isdir(platstdlib_dir)): + warn(f'Failed to find the platform-specifc standard library directory ({platstdlib_dir=})') + config['_error'] = missing_stdlib = True + + # Hint possible causes + if missing_stdlib: + if ENV_PYTHONHOME: + warn('\nHint') + warn(f'| The home directory was manually set to {ENV_PYTHONHOME!r} via the PYTHONHOME environment variable.') + warn('| This value might point to an invalid Python home directory.') + config['module_search_paths'] = pythonpath config['module_search_paths_set'] = 1