FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

[3.15] Re-entrant calls to `site.addsitedir()` can fail (affecting uv run) · Issue #149504 · python/cpython · GitHub

[3.15] Re-entrant calls to site.addsitedir() can fail (affecting uv run) #149504

Description

Bug report

Bug description:

I found a regression in Python 3.15’s site.py startup-file processing. A .pth file containing an import line that calls site.addsitedir() can re-enter process_startup_files() while _exec_imports() is iterating _pending_importexecs, causing recursive processing of the same .pth file and eventually a startup failure.

This was originally observed with uv run --with ..., because uv creates an ephemeral overlay .pth file like:

import site; site.addsitedir("/path/to/overlay/site-packages"); site.addsitedir("/usr/local/lib/python3.15/site-packages")

But the issue can be reproduced without uv.

Environment

Python 3.15.0b1+ (heads/3.15:e81025e6d2e, May 7 2026, 10:29:46)
[Clang 15.0.0 (clang-1500.3.9.4)]
macOS arm64

Minimal Reproducer

mkdir -p /tmp/site-repro/root /tmp/site-repro/overlay
printf 'import site; site.addsitedir("/tmp/site-repro/overlay")\n' > /tmp/site-repro/root/reenter.pth

python3.15 -S -c 'import site; site.addsitedir("/tmp/site-repro/root"); print("done")'

Expected Behavior

The .pth import line should execute once, add /tmp/site-repro/overlay as a site directory, and the command should print:

done

Actual Behavior

Python repeatedly processes the same .pth import line, then fails with errors like:

Error in import line from /tmp/site-repro/root/reenter.pth: import site; site.addsitedir("/tmp/site-repro/overlay")
...
RuntimeError: dictionary changed size during iteration

In startup contexts, such as uv run --with ..., this can become fatal during site initialization:

Fatal Python error: init_import_site: Failed to import the site module
Python runtime state: core initialized
Traceback (most recent call last):
  File "<frozen site>", line 901, in <module>
  File "<frozen site>", line 877, in main
  File "<frozen site>", line 812, in venv
  File "<frozen site>", line 598, in addsitepackages
  File "<frozen site>", line 422, in addsitedir
  File "<frozen site>", line 359, in process_startup_files
  File "<frozen site>", line 303, in _exec_imports
RuntimeError: dictionary changed size during iteration

Likely Cause

In Lib/site.py, addsitedir() calls process_startup_files() unless defer_processing_start_files=True.

process_startup_files() calls _exec_imports(), which iterates directly over _pending_importexecs.items():

def _exec_imports():
    for filename, imports in _pending_importexecs.items():
        ...
        for line in imports:
            exec(line)

If one of those .pth import lines calls site.addsitedir(), then addsitedir() calls process_startup_files() again while the outer _exec_imports() is still iterating _pending_importexecs. That causes repeated execution and eventually RuntimeError: dictionary changed size during iteration.

Real-World Trigger

With uv 0.11.7:

uv run --python /Users/jelle/py/cpython/python.exe --with iniconfig python -c 'import iniconfig'

fails before user code runs because uv’s ephemeral overlay .pth contains import site; site.addsitedir(...).

Plain uv run without --with works, so this is specifically triggered by .pth import lines that call site.addsitedir() during site startup.

CPython versions tested on:

3.15

Operating systems tested on:

macOS

Linked PRs

Activity

JelleZijlstra commented on May 7, 2026

MemberAuthor

cc @warsaw (pretty sure this is PEP-829)

brettcannon commented on May 7, 2026

Member

Might be a duplicate of #75723 which has a PR.

added
stdlibStandard Library Python modules in the Lib/ directory
on May 7, 2026
added a commit that references this issue on May 7, 2026
added a commit that references this issue on May 7, 2026

warsaw commented on May 11, 2026

Member

Might be a duplicate of #75723 which has a PR.

I think that one's different, and I just landed a fix for it for 3.15, but it can't be backported to 3.13 and 3.14. I am going to take a look at the PR above later.

warsaw commented on May 11, 2026

Member

Confirmed, and yes the problem is that the site.addsitedir() in the .pth file hits the same global dictionaries that are being iterated over.

I need to think about this further because you can't just copy the dictionaries before iterating over them. process_startup_files() clears them after processing, and you don't want to be sure not to lose the re-entrantly added entries. Let me work up a test case, and then I have some ideas.

added a commit that references this issue on May 13, 2026
added a commit that references this issue on May 13, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    stdlibStandard Library Python modules in the Lib/ directorytype-bugAn unexpected behavior, bug, or error

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions


      Back | FazBrowse Home | New Git URL