I was playing the the Python's import system in order to understand better how it works, and I encountered another problem. I have the following structure
pkg/ __init__.py c.py d.py subpkg/ __init__.py a.py b.py
Inside a.py
I have the following code:
from . import b from .. import d
And inside c.py
I have the following:
import subpkg.a
Now I receive the following error:
ValueError: attempted relative import beyond top-level package
But why? How can I solve it? I am running c.py
from the IDLE, and pkg
should be considered a package, since it has the __init__.py
file.
The first import works fine, but it's the following that doesn't work:
from .. import d
Because I am attempting to import something from a parent package, but apparently I cannot, for some weird reason.
The beyond top level package error in relative import error occurs when you use a relative import without the file you are importing being part of a package. To fix this error, make sure that any directories that you import relatively are in their own packages.
Relative imports use dot(.) notation to specify a location. Single dot specifies that the module is in the current directory, two dots indicate that module is in its parent directory of the current location and three dots indicate that it is in grandparent directory and so on.
The __init__.py file makes Python treat directories containing it as modules. Furthermore, this is the first file to be loaded in a module, so you can use it to execute code that you want to run each time a module is loaded, or specify the submodules to be exported.
Python 3 changed the import system so every time you want a module that is around the one you are working, you need relative imports (unless you mess with PYTHONPATH
or sys.path
).
The correct usage here should be
from .subpkg import a
When you are working with IDLE, you have a totally different environment. Therefore, you could add the current location to your path so imports work again.
try:
sys.path.insert(0, '')
It might be weird, but it is for a greater good
PS: If this last thing do not work -- I don't have an IDLE environment right now -- it is probably because the work directory is set wrong.
Try this answer instead: https://stackoverflow.com/a/17361545/754991
This had me question my insanity.
The problem stems from the confusion that people mistakenly take the relative import as path relative which is not.
Relative imports depend on the location of the file that is run.
This answer goes deeper into explaining how the python modules actually work, but to summarize.
__main__
.pkg.subpkg.a
from ..
there must be at least 2 dots in the file name. from ...
- 3 dots.Now comes the funny part.
If you run c.py directly, then it is given the name __main__
and a.py has subpkg.a
.
As per the 2nd statement, you must have at least 2 dots in the name of subpkg.a
to run from ..
inside it.
The fix
Create a new file outside the pkg, say main.py
pkg/ __init__.py c.py d.py subpkg/ __init__.py a.py b.py main.py
Inside main.py
import pkg.c
If we run main.py, it get's the name __main__
, and a.py get's pkg.subpkg.a
. As per the 2nd statement it now has 2 dots in the name and we can do the from ..
One more thing. Now that c.py is loaded as a module, we have to use from to load a.py.
from .subpkg import a
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With