relative import from __init__.py file throws error

thewellis picture thewellis · Apr 8, 2014 · Viewed 9.9k times · Source

So I'm using a template set by a co-worker and as a newbie to python I may be missing something very obvious.

The main directory has the init file which has a module I need for the main python file that generates the error.

Co-worker used:

from . import X

Where X was the module, but when copying this (and a populated init file) to my own directory it generates this error:

ValueError: Attempted relative import in non-package

From google and SO I gather that this is perfectly fine and logical so I'm wondering, as a newbie, what I've missed.

Answer

Ferdinand Beyer picture Ferdinand Beyer · Apr 8, 2014

You have to understand how Python handles modules.

When you start the interpreter with a script, this script becomes the main module, with the matching name __main__.

When using import, other modules are searched in the search path, that you can also access (and change) using sys.path. The first entry of sys.path is usually empty and stands for the current directory.

A directory within the search path is a package if it contains a __init__.py file.

Now, when you execute a script within a directory that contains an __init__.py file, this script will become __main__ and the directory is not regarded as a package, as it is not in sys.path!

For example, consider the following directory layout:

root/
    pkg/
        __init__.py
        b.py
        c.py
    a.py

When you run python a.py from the root/ directory, you can import pkg/ and use relative imports within this package (e.g., from . import c in b.py or __init__.py).

When you run python b.py from the pkg directory, you cannot use relative imports since Python does not recognize pkg as a package: it is not in sys.path. For Python, pkg is an ordinary directory, no matter if it contains a __init__.py. The fully qualified name of c.py is just c, not pkg.c, so a relative from . import c won't work.