I have a project structured as such:
folder1
|
folder2
|
tests
I have __init__.py in each folder. When I am in the parent directory of folder1, I run iPython and do
from folder1.folder2.tests.test1 import main
main()
everything works fine. However when I run
python folder1/folder2/tests/test1.py
I get ImportError: No module named folder1.folder2.file1, where my import statement in test1 is
from folder1.folder2.file1 import class1
Confused about this - I am guessing it is a path issue but I don't understand what is wrong with my code (many similar setups in other folders) and why it still works in iPython and not python run as a script.
The module search path (python 3 docu) is different with and without a script file:
interactive python interpreter
(goes for both python
and ipython
)
$ python
Python 2.7.3 (default, Dec 18 2014, 19:10:20)
[GCC 4.6.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> print(sys.path)
['', '/usr/lib/python2.7', '/usr/lib/python2.7/plat-linux2', '/usr/lib/python2.7/lib-tk', '/usr/lib/python2.7/lib-old', '/usr/lib/python2.7/lib-dynload', '/usr/local/lib/python2.7/dist-packages', '/usr/lib/python2.7/dist-packages', '/usr/lib/python2.7/dist-packages/PIL', '/usr/lib/pymodules/python2.7/gtk-2.0', '/usr/lib/python2.7/dist-packages/gst-0.10', '/usr/lib/python2.7/dist-packages/gtk-2.0', '/usr/lib/pymodules/python2.7', '/usr/lib/python2.7/dist-packages/ubuntu-sso-client', '/usr/lib/python2.7/dist-packages/ubuntuone-client', '/usr/lib/python2.7/dist-packages/ubuntuone-control-panel', '/usr/lib/python2.7/dist-packages/ubuntuone-couch', '/usr/lib/python2.7/dist-packages/ubuntuone-installer', '/usr/lib/python2.7/dist-packages/ubuntuone-storage-protocol']
>>>
Note the first entry being an empty string. An empty string is a relative path equivalent to .
. Relative paths in the module search path are relative to the current working dir of the interpreter process, so this is just the current working dir where you invoked the interpreter. (Which in your case happened to be the root of your project.)
executing a script file
$ echo 'import sys' > /tmp/pathtest.py
$ echo 'print(sys.path)' >> /tmp/pathtest.py
$ python /tmp/pathtest.py
['/tmp', '/usr/lib/python2.7', '/usr/lib/python2.7/plat-linux2', '/usr/lib/python2.7/lib-tk', '/usr/lib/python2.7/lib-old', '/usr/lib/python2.7/lib-dynload', '/usr/local/lib/python2.7/dist-packages', '/usr/lib/python2.7/dist-packages', '/usr/lib/python2.7/dist-packages/PIL', '/usr/lib/pymodules/python2.7/gtk-2.0', '/usr/lib/python2.7/dist-packages/gst-0.10', '/usr/lib/python2.7/dist-packages/gtk-2.0', '/usr/lib/pymodules/python2.7', '/usr/lib/python2.7/dist-packages/ubuntu-sso-client', '/usr/lib/python2.7/dist-packages/ubuntuone-client', '/usr/lib/python2.7/dist-packages/ubuntuone-control-panel', '/usr/lib/python2.7/dist-packages/ubuntuone-couch', '/usr/lib/python2.7/dist-packages/ubuntuone-installer', '/usr/lib/python2.7/dist-packages/ubuntuone-storage-protocol']
Note that here, the first entry is the absolute path of the directory containing the script file we passed as an argument.
I faced a similar issue while importing numpy or any library depending on numpy. The problem was that I had a file name random.py in my project folder.
Numpy has random.py in it for its random functions, but importing it was taking the random.py of my project folder.
The best solution is to not to name any file with the standard module names of any library.
Enjoy.. :)