python / python/cpython

Python on Windows, `site_import=0`/`-S`: `sys.path` containing executable path is undocumented

未關閉
#135,769 5 則留言 0 個 reaction 已指派 1 人 在 GitHub 檢視

@boimart1 已經在處理了。

開始於 2025年6月25日。

interpreter-core OS-windows type-bug
主要語言
Python
星號
77.2k
分支
36k
PR 合併指標
PR 指標待擷取

描述

Bug report

Bug description:

I'm noticing a discrepancy between running embedded Python with isolated=1 and site_import=0, and running a Python script with the equivalent flags -I -S. I'm unsure if this is intentional or not, or if this has any actual consequences, so I'm reporting it to be sure. This is potentially related to #131484.

The difference I'm seeing is that when running a python script, the 4th path in sys.path is C:\Python313; running an embedded application, the 4th path is the embedding executable's parent directory, e.g. C:\Work\Demos\py-embed-path\build\Debug.

In fact, in both cases, the 4th path is sys.executable's parent directory. But for embedded applications, I'm unsure if this is intentional, or if it should in fact also be C:\Python313, the directory containing python313.dll that the executable loaded.

To reproduce

On Windows, with Python 3.13.3 installed, given the following source files:

# script.py
import sys, os

print(f'{sys.executable=}')
print(f'{sys.prefix=}')
print(f'{os.getcwd()=}')

print('sys.path:')
for path in sys.path:
    print(f'- {path}')
// main.cpp
#include <Python.h>

int main() {
    PyConfig config;
    PyConfig_InitIsolatedConfig(&config);
    config.site_import = 0;

    PyStatus s = Py_InitializeFromConfig(&config);
    PyConfig_Clear(&config);

    if (PyStatus_Exception(s)) {
        Py_ExitStatusException(s);
    }

    PyRun_SimpleString(R"(
import sys, os

print(f'{sys.executable=}')
print(f'{sys.prefix=}')
print(f'{os.getcwd()=}')

print('sys.path:')
for path in sys.path:
    print(f'- {path}')
)");

    Py_Finalize();
    return 0;
}
# CMakeLists.txt
cmake_minimum_required(VERSION 3.12)
project(PythonPathRepro)
find_package(Python3 3.13 REQUIRED COMPONENTS Development.Embed)
add_executable(python_path_repro main.cpp)
target_link_libraries(python_path_repro PRIVATE Python3::Python)

if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
  # disable Python's auto-linking
  target_link_options(python_path_repro PRIVATE "/NODEFAULTLIB:python313_d.lib" "/NODEFAULTLIB:python313.lib")
endif()

Running the python script with the -I -S flags produces the following:

λ py -3.13 -I -S script.py
sys.executable='C:\\Python313\\python.exe'
sys.prefix='C:\\Python313'
os.getcwd()='C:\\Work\\Demos\\py-embed-path'
sys.path:
- C:\Python313\python313.zip
- C:\Python313\DLLs
- C:\Python313\Lib
- C:\Python313

Compiling and running the C++ code produces the following:

(I made sure to run the code from a different directory than the executable to demonstrate that the path is deduced from the executable, not from the cwd)

λ build\Debug\python_path_repro.exe 
sys.executable='C:\\Work\\Demos\\py-embed-path\\build\\Debug\\python_path_repro.exe'
sys.prefix='C:\\Python313'
os.getcwd()='C:\\Work\\Demos\\py-embed-path'
sys.path:
- C:\Python313\python313.zip
- C:\Python313\DLLs
- C:\Python313\Lib
- C:\Work\Demos\py-embed-path\build\Debug

These two modes of executions produce a different value for the fourth item in sys.path.

Notes

I understand that the repro above is not the usual use-case for embedded Python, and that it's better to include the Python "Windows embeddable package" in the app and use that, and possibly fully control sys.path through config.search_module_paths or python313._pth in the embeddable package. I am indeed using the embeddable package for the actual app. But the use-case I'm working with here is rather when building and running unit tests on developers' machines using their Python installation. Installing the embeddable package just to run the unit tests is something I would like to avoid, if possible, considering a full Python installation is already required to build the library and tests in the first place.

As I stated above, this difference in behavior is not actually causing any problems for the moment. I'm just reporting it in case it could potentially cause problems in the future, and to understand if this behavior is intended or not.

p.s. is there a reason for sys.path to contain C:\Python313 when running scripts with python.exe? By default, Python does not seem to have any modules available there. And the embeddable package which does have modules in its root directory also provides a python313._pth which overrides sys.path to include ..

CPython versions tested on:

3.13

Operating systems tested on:

Windows

貢獻指南

開啟貢獻指南

從這裡開始

  1. 先讀完整個 Issue,再讀專案的貢獻指南。
  2. 在 Issue 下留言說明你要接手 —— 這能避免兩個人做同樣的事。
  3. Fork 儲存庫,在一個分支上完成修改。
  4. 送出 Pull Request,並在描述裡引用這個 Issue 編號。

評估

這個 Issue 還沒有評估資料。

把新 issue 寄到你的電子郵件信箱

精選適合新手參與的 GitHub issue 摘要。