This question is related to Can't import module with importlib.import_module, which I don't think got to the root of the issue at all.
I'm trying to understand the reason for differences with importlib used in the interactive interpreter vs. a non-interactive script, because I'm getting different results with each.
I have a folder containing myscript.py, and I want it to import a module called module from a subfolder, my_subdir of the initial working directory. I want to do this by moving into that directory and working there. I know there are other solutions to accessing a module in a subdirectory, but this is the use case that I'd like to talk about.
The following is the contents of myscript.py, which simply moves into the subdirectory and tries to import the module from there, and then call some hello-world function from the module:
#!/home/chris/anaconda2/bin/python
import sys
import platform
import os
import importlib
print("Python version "+ platform.python_version())
print(sys.path)
os.chdir('my_subdir')
my_module = importlib.import_module('module')
my_module.my_function()
When I run this from the command line, Python can't find the module. It seems that the import system doesn't know about the change of directory from os.chdir():
(base) chris@linux-om3m:~/workspace> python myscript.py
Python version 2.7.15
['/home/chris/workspace', '/home/chris/anaconda2/lib/python27.zip', '/home/chris/anaconda2/lib/python2.7', '/home/chris/anaconda2/lib/python2.7/plat-linux2', '/home/chris/anaconda2/lib/python2.7/lib-tk', '/home/chris/anaconda2/lib/python2.7/lib-old', '/home/chris/anaconda2/lib/python2.7/lib-dynload', '/home/chris/anaconda2/lib/python2.7/site-packages', '/home/chris/anaconda2/lib/python2.7/site-packages']
Traceback (most recent call last):
File "myscript.py", line 11, in <module>
my_module = importlib.import_module('module')
File "/home/chris/anaconda2/lib/python2.7/importlib/__init__.py", line 37, in import_module
__import__(name)
ImportError: No module named module
However, when I type the same script into the interactive interpreter, it works fine:
(base) chris@linux-om3m:~/workspace> python
Python 2.7.15 | packaged by conda-forge | (default, Jul 2 2019, 00:39:44)
[GCC 7.3.0] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> import platform
>>> import os
>>> import importlib
>>> print("Python version "+ platform.python_version())
Python version 2.7.15
>>> print(sys.path)
['', '/home/chris/anaconda2/lib/python27.zip', '/home/chris/anaconda2/lib/python2.7', '/home/chris/anaconda2/lib/python2.7/plat-linux2', '/home/chris/anaconda2/lib/python2.7/lib-tk', '/home/chris/anaconda2/lib/python2.7/lib-old', '/home/chris/anaconda2/lib/python2.7/lib-dynload', '/home/chris/anaconda2/lib/python2.7/site-packages', '/home/chris/anaconda2/lib/python2.7/site-packages']
>>> os.chdir('my_subdir')
>>> my_module = importlib.import_module('module')
>>> my_module.my_function()
Here I am!
>>>
I can fix this issue by manually updating sys.path with a sys.path.append(os.getcwd()) after I do the os.chdir - but I do not understand why this is only necessary in non-interactive mode.
The only thing I do notice (and is printed here in the pasted output) is that under the interactive interpreter, sys.path has an empty-string entry, whereas in non-interactive mode it contains the working dir where I invoked python.
I know I could fix this problem using relative imports, and for now I'm fixing the problem using a sys.path.append(os.getcwd()), but I'd like to understand why there is a difference between running interactively vs. non-interactively.
I'm getting the same results with Python 2.7 and Python 3.6.