I made a test of shadowing Python's built-in string module with my own
module named 'string', to test module search path behavior. My custom
string script has only print('string' * 2)
for contents. It is
located in the current directory as shown in code below.
Python 3.6.4 |Anaconda custom (64-bit)| (default, Jan 16 2018, 10:22:32) [MSC v.1900 64 bit (AMD64)]
Type 'copyright', 'credits' or 'license' for more information
IPython 6.2.1 -- An enhanced Interactive Python. Type '?' for help.
In [1]: %pwd
Out[1]: 'C:\\Users\\stephen'
In [2]: import string
In [3]: string
Out[3]: <module 'string' from 'C:\\ProgramData\\Anaconda3\\lib\\string.py'>
In [4]: import imp
In [5]: imp.reload(string)
stringstring
Out[5]: <module 'string' from 'C:\\Users\\stephen\\string.py'>
Three questions about reload in IPython:
Edit: In going back and forth trying to take care of Stack Overflow complaining about my code block, I inadvertently lost some of what I meant to say. Here is what I can remember: IPython is adding the built-in string module to sys.modules dictionary at startup (sys.modules is searched before sys.path), something the regular Python interactive prompt doesn't do. So I got a different behavior from the interactive prompt vs. IPython. With the interactive prompt, I always got the local string.py, since sys.path starts with current directory for module search. So, this much I understand about the difference between regular interactive (Anaconda) and IPython. The questions I listed are what remain confusing for me.
reload
is supposed to repeat the process of locating the source code for the module it's reloading, and if it finds a different file from what the original import found, it's supposed to use the new file. After all, it needs to handle cases where a module was moved, or where a normal module was changed to a package or an extension module.
reload
is not supposed to look at sys.modules
and stop if it finds something. If it did that, it would perform no reloading!
The reason reload
finds the local string.py
file when the initial IPython-internal import didn't is because the import path has changed since the first import. You ran IPython in a way that doesn't cause Python itself to put the working directory on the module search path, and IPython imported the string
module from the standard library under that configuration. Afterward, IPython placed the working directory on the module search path itself, mimicking regular interactive Python, so reload
found the local string.py
.