Relative imports - ModuleNotFoundError: No module named x
TL;DR: You can't do relative imports from the file you execute since
__main__ module is not a part of a package.
Absolute imports - import something available on
Relative imports - import something relative to the current module, must be a part of a package
If you're running both variants in exactly the same way, one of them should work. Here is an example that should help you understand what's going on. Let's add another
main.py file with the overall directory structure like this:
And let's update
test.py to see what's going on:
# config.pydebug = True
# test.pyprint(__name__)try: # Trying to find module in the parent package from . import config print(config.debug) del configexcept 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.pyimport ryan.test
$ python ryan/test.py__main__Relative import failedTrue
Here "test" is the
__main__ module and doesn't know anything about belonging to a package. However
import config should work, since the
ryan folder will be added to
$ python main.pyryan.testTrueAbsolute 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 you're sticking with Python 3 there is no more need for
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
def does_something(): return "I gave you this string."
from modx import does_somethingdef loaded(): string = does_something() print(string)
from lib import modymody.loaded()
when I execute main, this is what happens
$ python main.pyTraceback (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_somethingImportError: 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)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.pyRefactoringTool: lib/mody.py-
I had to modify mody.py's import statement to fix it
try: from modx import does_somethingexcept ImportError: from .modx import does_somethingdef loaded(): string = does_something() print(string)
Then I ran main.py again and got the expected output
$ python main.pyI gave you this string.
Lastly, just to clean it up and make it portable between 2 and 3.
from __future__ import absolute_importfrom .modx import does_something
You have to append your project's path to
PYTHONPATH and make sure to use absolute imports.
For UNIX (Linux, OSX, ...)
Assuming that we have the following project structure,
└── myproject ├── mypackage │ ├── a.py └── anotherpackage ├── b.py ├── c.py └── mysubpackage └── d.py
just make sure to reference each import starting from the project's root directory. For instance,
# in module a.pyimport anotherpackage.mysubpackage.d# in module bimport anotherpackage.cimport mypackage.a
For a more comprehensive explanation, refer to the article How to fix ModuleNotFoundError and ImportError