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