Skip to content

Regression in sys.path construction behaviour of Py_InitializeFromConfig()  #92913

Closed
@freakboy3742

Description

@freakboy3742

Bug report

3.11.0b1 appears to have a regression in the behavior of Py_InitializeFromConfig() in the way that sys.path is computed.

Reproduction case 1:

This code attempts to set the path through the config.pythonpath_env variable.

int main(int argc, char *argv[]) {
    PyConfig config;
    PyConfig_InitIsolatedConfig(&config);

    PyConfig_SetString(&config, &config.pythonpath_env, L"/path/to/app:/other/path");

    Py_InitializeFromConfig(&config);   
    PyRun_SimpleString("import sys; print(f'{sys.path=}')");
    return 0
}

In Python 3.8.13, 3.9.12 and 3.10.4, this code shows 6 items when sys.path is printed:

  • /path/to/app
  • /other/path
  • /path/to/Python/lib/python3X.zip
  • /path/to/Python/lib/python3.X
  • /path/to/Python/lib/python3.X/lib-dynload
  • /path/to/Python/lib/python3.X/site-packages

In Python 3.11.0b1, the first two items are not present.

Reproduction case 2:

This example is a closer match to the "more complete example" in the docs; it reads a full configuration, then appending the extra search paths.

int main(int argc, char *argv[]) {
    PyConfig config;
    PyConfig_InitIsolatedConfig(&config);

    PyConfig_Read(&config);
    PyWideStringList_Append(&config.module_search_paths, L"/path/to/app");
    PyWideStringList_Append(&config.module_search_paths, L"/other/path");

    Py_InitializeFromConfig(&config);   
    PyRun_SimpleString("import sys; print(f'{sys.path=}')");
    return 0
}

Again, in Python 3.8.13, 3.9.12 and 3.10.4, this code shows 6 items when sys.path is printed (although the order is different):

  • /path/to/Python/lib/python3X.zip
  • /path/to/Python/lib/python3.X
  • /path/to/Python/lib/python3.X/lib-dynload
  • /path/to/app
  • /other/path
  • /path/to/Python/lib/python3.X/site-packages

In Python 3.11.0b1, this raises an error, dumping the path configuration with _Py_DumpPathConfig(). This appears to be because it's modifying the path enough to make the encodings module unimportable.

If the 2 path appends are omitted (but the PyConfig_Read() call is retained), it runs, and outputs sys.path - but with the 2 custom module search paths missing.

Analysis

As best as I can make out, the regression was introduced by 99fcf15 (cc @zooba) as part of a refactor of getpath().

Your environment

Observed in Python 3.11.0b1 on macOS 12.3.1 on M1 hardware; however, I don't think there's anything Mac specific about it.

FWIW, I discovered this while porting the support library used by Briefcase to publish macOS and iOS apps.

Metadata

Metadata

Assignees

No one assigned

    Labels

    type-bugAn unexpected behavior, bug, or error

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions