How do imports work in IPython

orodbhen picture orodbhen · Aug 13, 2014 · Viewed 12.6k times · Source

I'm a little bewildered by exactly how import statements work in IPython. I've turned up nothing through web searches.

Implicit relative imports work with Python 2, but I don't know if that's still the case with IPython for Python 3.

Relative imports using the dot syntax dont seem to work at all:

In [6]: ls 
dsp/  __init__.py  __init__.pyc  utils/

In [7]: from .utils import capture
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-7-e7d50007bdd1> in <module>()
----> 1 from .utils import capture

ValueError: Attempted relative import in non-package

importing modules that use the dot syntax seems impossible:

In [8]: cd utils
/home/user/workspace/mypkg/mypkg/utils

In [9]: ls
capture/  capture.py  capture.pyc  cext/  __init__.py  __init__.pyc

In [10]: from capture import Capture
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-10-8c31c76d052d> in <module>()
----> 1 from capture import Capture

/home/user/workspace/mypkg/mypkg/utils/capture.py in <module>()
     17 import tarfile
     18 import re
---> 19 from .. import utils
     20 from . import flprint
     21 from select import poll

ValueError: Attempted relative import in non-package

Is there some concise documentation on this somewhere?

Answer

orodbhen picture orodbhen · Aug 15, 2014

The problem is I was importing the module from a lower position in the package hierarchy than is used in the module's import statement. So if I cd into the utils directory and run

from capture import Capture

then capture becomes the top level of the hierarchy. So the import statement in the capture module

from .. import utils

goes beyond the top level. Python doesn't know what ".." refers to, because modules aren't self-aware of what package they belong to. If I change back up to the mypkg directory, I get the same problem

In [13]: cd ..
/home/user/workspace/myproj/mypkg

In [14]: from utils import capture
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-14-c87f26b2171d> in <module>()
----> 1 from utils import capture

/home/user/workspace/myproj/mypkg/utils/capture.py in <module>()
    18 import re
    19 import zmq
---> 20 from .. import utils
    21 from . import flprint
    22 from select import poll

ValueError: Attempted relative import beyond toplevel package

In this case, utils is the top level, so

from . import flprint

will work, but

from .. import utils

won't work.

I have to move one more directory up:

In [19]: cd ..
/home/user/workspace/myproj

In [20]: from mypkg.utils import capture

In [21]: cap = capture.Capture

IPython can import packages and modules located in the current working directory, or from directories in the import path. I can add the package to the import path to be able to import from any working directory.

In [23]: import sys

In [24]: sys.path.append('/home/user/workspace/myproj')

In [25]: cd
/home/user

In [26]: from mypkg.utils import capture

You can use sys.path.append to make your module "self-aware" but, as pointed out by alpha_989, it can potentially lead to name collisions. However, it is a useful workaround when doing work inside the package hierarchy from an interactive terminal session.