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?
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.