Skip to content

coverage run in isolated mode does not preserve sys.path correctly Python 3.10 #2103

@Maillol

Description

@Maillol

Describe the bug
When running coverage run with the -I flag (isolated mode) under Python 3.12, the initial sys.path differs from the behavior under Python 3.10.
Under Python 3.10 the current working directory is incorrectly included in sys.path.
The path entry sys.path[1] is unexpectedly removed instead of sys.path[0].

To Reproduce

$ cd /tmp
$ echo 'import sys;print("sys.flags:", sys.flags);print("sys.path:", sys.path)' > poc.py
$ python3.10 -m venv venv310
$ python3.12 -m venv venv312
$ ./venv310/bin/pip install coverage==7.12.0
$ ./venv312/bin/pip install coverage==7.12.0
$ ./venv310/bin/python3.10 -Im coverage run poc.py 
sys.flags: sys.flags(debug=0, inspect=0, interactive=0, optimize=0, dont_write_bytecode=0, no_user_site=1, no_site=0, ignore_environment=1, verbose=0, bytes_warning=0, quiet=0, hash_randomization=1, isolated=1, dev_mode=False, utf8_mode=0, warn_default_encoding=0, int_max_str_digits=-1)
sys.path: ['/tmp', '/usr/lib/python3.10', '/usr/lib/python3.10/lib-dynload', '/tmp/venv310/lib/python3.10/site-packages']
$./venv312/bin/python3.12 -Im coverage run poc.py 
sys.flags: sys.flags(debug=0, inspect=0, interactive=0, optimize=0, dont_write_bytecode=0, no_user_site=1, no_site=0, ignore_environment=1, verbose=0, bytes_warning=0, quiet=0, hash_randomization=1, isolated=1, dev_mode=False, utf8_mode=0, warn_default_encoding=0, safe_path=True, int_max_str_digits=4300)
sys.path: ['/usr/lib/python312.zip', '/usr/lib/python3.12', '/usr/lib/python3.12/lib-dynload', '/tmp/venv312/lib/python3.12/site-packages']

Answer the questions below:

  1. What version of Python are you using?
    python3.10 and python3.12

  2. What version of coverage.py shows the problem? The output of coverage debug sys is helpful.

./venv312/bin/python3.12 -m coverage debug sys
-- sys -------------------------------------------------------
               coverage_version: 7.12.0
                coverage_module: /tmp/venv312/lib/python3.12/site-packages/coverage/__init__.py
                           core: -none-
                        CTracer: available from /tmp/venv312/lib/python3.12/site-packages/coverage/tracer.cpython-312-x86_64-linux-gnu.so
           plugins.file_tracers: -none-
            plugins.configurers: -none-
      plugins.context_switchers: -none-
              configs_attempted: /tmp/.coveragerc
                                 /tmp/setup.cfg
                                 /tmp/tox.ini
                                 /tmp/pyproject.toml
                   configs_read: -none-
                    config_file: None
                config_contents: -none-
                      data_file: -none-
                         python: 3.12.7 (main, Oct  1 2024, 08:52:12) [GCC 11.4.0]
                       platform: Linux-6.8.0-45-generic-x86_64-with-glibc2.39
                 implementation: CPython
                          build: main
                                 Oct  1 2024 08:52:12
                    gil_enabled: True
                     executable: /tmp/venv312/bin/python3.12
                   def_encoding: utf-8
                    fs_encoding: utf-8
                            pid: 12181
                            cwd: /tmp
                           path: /tmp
                                 /usr/lib/python312.zip
                                 /usr/lib/python3.12
                                 /usr/lib/python3.12/lib-dynload
                                 /tmp/venv312/lib/python3.12/site-packages
                    environment: HOME = /home/maillol
                   command_line: /tmp/venv312/lib/python3.12/site-packages/coverage/__main__.py debug sys
                           time: 2025-12-08 09:25:36
./venv310/bin/python3.10 -m coverage debug sys
-- sys -------------------------------------------------------
               coverage_version: 7.12.0
                coverage_module: /tmp/venv310/lib/python3.10/site-packages/coverage/__init__.py
                           core: -none-
                        CTracer: available from /tmp/venv310/lib/python3.10/site-packages/coverage/tracer.cpython-310-x86_64-linux-gnu.so
           plugins.file_tracers: -none-
            plugins.configurers: -none-
      plugins.context_switchers: -none-
              configs_attempted: /tmp/.coveragerc
                                 /tmp/setup.cfg
                                 /tmp/tox.ini
                                 /tmp/pyproject.toml
                   configs_read: -none-
                    config_file: None
                config_contents: -none-
                      data_file: -none-
                         python: 3.10.18 (main, Jun  4 2025, 08:56:00) [GCC 13.3.0]
                       platform: Linux-6.8.0-45-generic-x86_64-with-glibc2.39
                 implementation: CPython
                          build: main
                                 Jun  4 2025 08:56:00
                    gil_enabled: True
                     executable: /tmp/venv310/bin/python3.10
                   def_encoding: utf-8
                    fs_encoding: utf-8
                            pid: 12199
                            cwd: /tmp
                           path: /tmp
                                 /usr/lib/python310.zip
                                 /usr/lib/python3.10
                                 /usr/lib/python3.10/lib-dynload
                                 /tmp/venv310/lib/python3.10/site-packages
                    environment: HOME = /home/maillol
                   command_line: /tmp/venv310/lib/python3.10/site-packages/coverage/__main__.py debug sys
                           time: 2025-12-08 09:25:45

Expected behavior

Under Python 3.10

sys.path: ['/usr/lib/python310.zip', '/usr/lib/python3.10', '/usr/lib/python3.10/lib-dynload', '/tmp/venv310/lib/python3.10/site-packages']

Additional context

The incorrect behavior under Python 3.10 seems to have been present since coverage 5.0.3.
This issue also appears related to how coverage.execfile.PyRunner handles the safe_path flag.
However, this flag does not exist in Python 3.10, which may contribute to the inconsistent behavior between Python 3.10 and Python 3.12.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions