python – Relative imports – ModuleNotFoundError: No module named x
python – Relative imports – ModuleNotFoundError: No module named x
TL;DR: You cant do relative imports from the file you execute since __main__
module is not a part of a package.
Absolute imports – import something available on sys.path
Relative imports – import something relative to the current module, must be a part of a package
If youre running both variants in exactly the same way, one of them should work. Here is an example that should help you understand whats going on. Lets add another main.py
file with the overall directory structure like this:
.
./main.py
./ryan/__init__.py
./ryan/config.py
./ryan/test.py
And lets update test.py
to see whats going on:
# config.py
debug = True
# test.py
print(__name__)
try:
# Trying to find module in the parent package
from . import config
print(config.debug)
del config
except ImportError:
print(Relative import failed)
try:
# Trying to find module on sys.path
import config
print(config.debug)
except ModuleNotFoundError:
print(Absolute import failed)
# main.py
import ryan.test
Lets run test.py
first:
$ python ryan/test.py
__main__
Relative import failed
True
Here test is the __main__
module and doesnt know anything about belonging to a package. However import config
should work, since the ryan
folder will be added to sys.path
.
Lets run main.py
instead:
$ python main.py
ryan.test
True
Absolute import failed
And here test is inside of the ryan package and can perform relative imports. import config
fails since implicit relative imports are not allowed in Python 3.
Hope this helped.
P.S.: If youre sticking with Python 3 there is no more need for __init__.py
files.
I figured it out. Very frustrating, especially coming from python2.
You have to add a .
to the module, regardless of whether or not it is relative or absolute.
I created the directory setup as follows.
/main.py
--/lib
--/__init__.py
--/mody.py
--/modx.py
modx.py
def does_something():
return I gave you this string.
mody.py
from modx import does_something
def loaded():
string = does_something()
print(string)
main.py
from lib import mody
mody.loaded()
when I execute main, this is what happens
$ python main.py
Traceback (most recent call last):
File main.py, line 2, in <module>
from lib import mody
File /mnt/c/Users/Austin/Dropbox/Source/Python/virtualenviron/mock/package/lib/mody.py, line 1, in <module>
from modx import does_something
ImportError: No module named modx
I ran 2to3, and the core output was this
RefactoringTool: Refactored lib/mody.py
--- lib/mody.py (original)
+++ lib/mody.py (refactored)
@@ -1,4 +1,4 @@
-from modx import does_something
+from .modx import does_something
def loaded():
string = does_something()
RefactoringTool: Files that need to be modified:
RefactoringTool: lib/modx.py
RefactoringTool: lib/mody.py
I had to modify mody.pys import statement to fix it
try:
from modx import does_something
except ImportError:
from .modx import does_something
def loaded():
string = does_something()
print(string)
Then I ran main.py again and got the expected output
$ python main.py
I gave you this string.
Lastly, just to clean it up and make it portable between 2 and 3.
from __future__ import absolute_import
from .modx import does_something
python – Relative imports – ModuleNotFoundError: No module named x
You have to append your projects path to PYTHONPATH
and make sure to use absolute imports.
For UNIX (Linux, OSX, …)
export PYTHONPATH=${PYTHONPATH}:/path/to/your/project/
For Windows
set PYTHONPATH=%PYTHONPATH%;C:pathtoyourproject
Absolute imports
Assuming that we have the following project structure,
└── myproject
├── mypackage
│ ├── __init__.py
│ ├── a.py
└── anotherpackage
├── __init__.py
├── b.py
├── c.py
└── mysubpackage
├── __init__.py
└── d.py
just make sure to reference each import starting from the projects root directory. For instance,
# in module a.py
import anotherpackage.mysubpackage.d
# in module b
import anotherpackage.c
import mypackage.a
For a more comprehensive explanation, refer to the article How to fix ModuleNotFoundError and ImportError