I create a dummy module module in /tmp
, insert
its path do sys.path
, import the dummy module, del
it when it's not needed anymore, remove it sys.path
and I am still able to import it. Why?
Consider this pytest fixture code and its comments:
def test_function(temp_dir):
with open(os.path.join(temp_dir, 'dum.py'), 'w') as f:
f.write("""
class A:
\"\"\"
test docstring
\"\"\"
test: int
test_2: str = "asdf"
class B(A):
pass
""")
import sys
sys.path.insert(1, temp_dir)
assert temp_dir in sys.path # assertion passes
# noinspection PyUnresolvedReferences
import dum # import successful
yield dum
# teardown executed after each usage of the fixture
del dum # deletion successful
sys.path.remove(temp_dir) # removing from path successful
assert temp_dir not in sys.path # assertion passes
with pytest.raises(ModuleNotFoundError): # fails - importing dum is successful
import dum
Why? How do I actually remove it? It happens even when I force sys.path to be empty by executing sys.path = []
. There is no dum.py
anywhere in the project directory. Am I missing something? Is Python caching the imported modules even after their deletion?
After you import a module once, the next time you want to import it, Python first checks the collection of already imported modules, and uses the module that was already loaded. Therefore, the second time you import a module, sys.path
is not even consulted.
This is essential, if you think of it: suppose you are directly importing some modules, and each of them uses, some other modules, and so on. If a module had to be retrieved from disk and parsed, every time an import
statement was encountered, you would be spending and awful lot of time just waiting for modules to load.
It is also worth noting that the second time a module A imports a module B, nothing really happens. There are ways to explicitly reload an already-loaded module, but usually, you do not want to do that (web servers with live update are a notable exception).