Python importlib.reload() had some difference between in 3.10 and 3.11

Hi everyone. My friend and I notice something strange.
The program in the Pic 2 firstly output the “a1” and “b” correctly, but after manually change the “a1” → “a” and “b” → “b1” and input the “reload” in the console. Something happened differently in two versions.

In 3.11:
Output: “a”, “b1”
In 3.10:
Output: “a”, “b”

My environments are V3.11.7 and V3.10.11 in Pycharm Build #PC-231.9011.38, built on May 17, 2023

My friend use 3.10 in system interpreter got same result as above.

We looked up the Python Docs in 3.10 and 3.11, notices there is no significant difference in “importlib.reload(module)” selections.

Can anyone tell us what is happening? That would be great, thank you.
image (1)
image (2)
image (3)
image

An important place to start is the “What’s New”. You’re fortunate here in that you have two adjacent versions (3.10 and 3.11) so you need only read one section (the changes in 3.11):

This is valuable alongside the main documentation for the reload function, since it’s possible that a change somewhere else affected what you’re doing.

However, in this case, I don’t think that’s what’s happened (there are a number of references to importlib, but they’re to do with importlib.resources and the module loader system). I’m not sure exactly what IS going on here, though, since I get the same result on several different versions of Python, back as far as 3.9 and all the way to current trunk: it prints “a1” and “b”. (Though I think I was doing things slightly differently from you - I had “a” and “b”, loaded up, then changed to “a1” and “b1” before reloading. In any case, the behaviour is the same across Python versions.)

Are you able to reproduce the same results outside of PyCharm? I was running the Python interpreter directly from the command line. Not sure if that would make any difference, but at very least, it’s worth eliminating as a possibility.

As a side note, I have never used importlib.reload() in production. Whenever I need dynamic updates, I usually end up doing something much simpler by avoiding the module system altogether and just exec’ing the code that I need. My “module objects” (which would be plain dictionaries in this form) can then easily be replaced, without worrying about the module cache getting in the way. It’s a little more work to set up, but in return, you have a guarantee that you won’t get bitten by something like this, since you KNOW which modules you’ve reloaded and which you haven’t.

Sorry, I can’t reproduce any difference. When I try it in 3.11, I get the reported 3.10 behaviour. Same in 3.8. Regardless of version, my output is a and then b.

This is as expected: reloading a doesn’t cause a.b to be removed from the module cache, so from .b import b_print reuses the existing module. Another simple way to verify this is with a global print in b.py.

Typing it out for others to test with:

Directory structure

.
├── a
│   ├── b.py
│   └── __init__.py
└── c.py

Contents of a/__init__.py

print("a1")

from .b import b_print

b_print()

Contents of a/b.py

def b_print():
    print("b")

Contents of c.py

import importlib

a = importlib.import_module("a")

while True:
    test = input("cmd>>>")

    if test == "reload":
        importlib.reload(a)
1 Like