python / python/cpython

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

Open
#135,769 5 comments 0 reactions 1 assignee View on GitHub

@boimart1 is already working on this.

Since Jun 25, 2025.

interpreter-core OS-windows type-bug
Dominant language
Python
Stars
77.2k
Forks
35.9k
PR merge metrics
PR metrics pending

Description

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

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.