Andrew Andrew - 3 months ago 9
Python Question

import fails when running python as script, but not in iPython?

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.

Answer

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.

Comments