Skip to content

cpython uses old cached bytecode when you change the source to fast #136224

@15r10nk

Description

@15r10nk

Bug report

Bug description:

I found a problem when I change python source code real fast and execute it again. It looks like cpython uses the old cached bytecode when the timestamp of the bytecode and the timestamp of the new source are the same (it looks like the resolution is 1 second because it uses st_mtime).

The following code demonstrates the problem:

from subprocess import run
import sys
import time

with open("import_print_number.py", "w") as f:
    f.write(
        """\
from print_number import print_number 
print_number()
"""
    )

for i in range(20):
    print("test", i)
    with open("print_number.py", "w") as f:
        f.write(f"def print_number(): print({i})")

    # low numbers make the bug more likely
    time.sleep(0.6)

    # run the code
    result = run([sys.executable, "import_print_number.py"], capture_output=True)

    n = int(result.stdout.decode().strip())

    # numbers should be equal but are not in some cases,
    # because python uses some old cached bytecode
    assert i == n, (i, n)

output (Python 3.11.2):

test 0
test 1
test 2
Traceback (most recent call last):
  File "/home/frank/projects/pysource-playground/pysource-minimize/bug.py", line 28, in <module>
    assert i == n, (i, n)
           ^^^^^^
AssertionError: (2, 1)

My current work around is that i delete __pycache__ every time I change code but It would be nice if this is not neccessary. It is also really hard to figure out what is going on when it happens because the problem is often not deterministic.

CPython versions tested on:

3.11, 3.14, 3.13, 3.12, 3.10, 3.9

Operating systems tested on:

Linux

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