Relative imports - ModuleNotFoundError: No module named x
Solution 1
As was stated in the comments to the original post, this seemed to be an issue with the python interpreter I was using for whatever reason, and not something wrong with the python scripts. I switched over from the WinPython bundle to the official python 3.6 from python.org and it worked just fine. thanks for the help everyone :)
Solution 2
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 sys.path
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:
.
./main.py
./ryan/__init__.py
./ryan/config.py
./ryan/test.py
And let's update test.py
to see what's 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
Let's run test.py
first:
$ python ryan/test.py
__main__
Relative import failed
True
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 sys.path
.
Let's 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 you're sticking with Python 3 there is no more need for __init__.py
files.
Solution 3
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.py's 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
Solution 4
You have to append your project's 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:\path\to\your\project\
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 project's 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
Solution 5
Setting PYTHONPATH can also help with this problem.
Here is how it can be done on Windows
set PYTHONPATH=.
Comments
-
blitzmann almost 2 years
This is the first time I've really sat down and tried python 3, and seem to be failing miserably. I have the following two files:
- test.py
- config.py
config.py has a few functions defined in it as well as a few variables. I've stripped it down to the following:
config.py
debug = True
test.py
import config print (config.debug)
I also have an
__init__.py
However, I'm getting the following error:
ModuleNotFoundError: No module named 'config'
I'm aware that the py3 convention is to use absolute imports:
from . import config
However, this leads to the following error:
ImportError: cannot import name 'config'
So I'm at a loss as to what to do here... Any help is greatly appreciated. :)
-
Copperfield almost 7 yearsI cannot reproduce the error, how do you execute this code?
-
blitzmann almost 7 yearsI execute
test.py
through pyCharm with Python 3.6. Does yours execute fine? -
Copperfield almost 7 yearsI execute it with idle that come with python, and also as
python test.py
, and it work perfectly fine. I don't have pyCharm, but perhaps is some bad configuration of pyCharm that is causing the problem -
blitzmann almost 7 yearsVery odd. I'm using WinPython - just download vanilla Python 3.6 from python.org, and it works fine. Never thought to check the interpreter! Thanks!
-
Martin Tournoij almost 7 yearsMy guess is that something funky is going on with PYTHONPATH. Check your IDE settings and/or system environment variables.
-
Admin over 6 yearsI have this same exact problem. It is not pycharm! It is python3. It works in python2, but when using python3, you see this error! very frustrating.
-
ParaH2 over 5 yearssys.path.append(r'C:/.../LastFolder') works all the time
-
mrgloom over 2 yearsIf I run it from console first option works for me and second gives me "ImportError: attempted relative import with no known parent package".
-
naoko almost 7 yearsHmm hate to say this but same thing just happened to me. Recreating environment fix the issue. In my case, I was getting this error when running tests. In the same environment, attempt to import same module worked. Recreating environment fixed them all (same python version 3.6)
-
James T. over 6 yearsIs there something I can do to make absolute imports always work? Like, call
sys.path.append('/some/path/my_module')
inside of/some/path/my_module/__init__.py
? -
Igonato over 6 years@JamesT. Yes, it's pretty common to modify
sys.path
during runtime (github.com/…). You can also set PYTHONPATH environment variable. -
Geek almost 6 yearssetting PYTHONPATH to main code directory solved the problem for me!
-
winux over 5 yearsDifferent IDE's have different way of handling path's specially for project source files (views, modules, templates, etc.) If your project is structured and coded properly, then it should work to all (standard) IDE's. Having issues with popular IDE's like WinPython means the problem is indeed coming from your project. As mentioned above, the problem is "You have to add a . to the module" by user3159377 which should be the accepted answer.
-
Kevin almost 5 years"if you're sticking with Python 3 there is no more need in
__init__.py
files." Interesting. Can you elaborate on this? I was under the impression that the package resolution mechanism hasn't changed all that much between 2 and 3. -
smci almost 5 years"if you're sticking with Python 3 there is no more need for
__init__.py
files." Conversely, can you describe things if we want a package to work in both 2 and 3? And see the woefully-out-of-date 2009 What is__init__.py
for? and its most highly-upvoted answer "It's a part of a package". We need to start emphasizing the distinction "regular package [old, pre-3.3]" vs "namespace package [3.3+]" everywhere and often. -
Mayur almost 5 yearsThis is what I was exactly looking for. Thanks for sharing this answer!!!
-
Tony Fraser over 4 yearsHuge thanks @Giorgos! This is especially true when you're trying to set a root directory in a docker image.
-
Sharad about 4 yearsDoing something like this gives a linter (pylint3) error. The error is similar to this one. filename.py:12:0: C0413: Import "import abc.def.ghi.file_util as file_util" should be placed at the top of the module (wrong-import-position)
-
Justapigeon about 4 yearsWorth noting that the
try/except
loading procedure is the real ingredient that works here (as some people will need to usetry:scripts.modx
andexcept: modx
), and was what solved this issue for me. -
rjdkolb about 4 yearsWorks in Linux as well. export PYTHONPATH=.
-
ingyhere over 3 yearsTry/except on import is ugly. I wish there was a better solution.
-
Giorgos Myrianthous over 3 yearsYou have to add a . to the module, regardless of whether or not it is relative or absolute This is not quite accurate. If you use the dot, then it becomes a relative import.
-
BVengerov over 3 yearsSorry for spamming in the comment section, but... man, thanks so much for your answer @Igonato!
-
VISQL over 3 yearsExcellent. These contents for the
__init__
file work in Python 3.6.6 -
torez233 almost 3 yearsthanks for the answer. I am wondering if in main.py, "from ryan import test" is equivalent to "import ryan.test" (ignore the namespace prefix differenence, i.e. in the former we can access via test while in the latter we have to access via ryan.test)? Are those two going to import the same set of variables defined in the namespace of test, and are they both absolute import?
-
Aidos almost 3 yearsthank you so much! this dot (.) was the actual problem for me =)
-
etoricky over 2 yearsI am using a library called
generateDS
and I add a dot at the module name and solve the problem in 2021! Thanks! -
user7630232 over 2 yearsThis worked like charm! thanks a lot.
-
mrgloom over 2 yearsWhat is "part of a package" here mean?
-
mrgloom over 2 yearsWhat is in the
sys.path
in this example? -
mrgloom over 2 yearsWhy we don't import it like "from ryan import config"?
-
llincolnatal about 2 yearsdon't forget
import sys
:) -
Admin about 2 yearsAs it’s currently written, your answer is unclear. Please edit to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers in the help center.
-
altela about 2 yearsadding . when importing a file (in my case, from .file1 import my_var) still working great in python 3.7, thank you
-
Harshad Vyawahare almost 2 yearsAnother version of the same answer, this also works:
sys.path.append(os.path.join(os.path.dirname(__file__), os.pardir))
Here omitted a few things like:os.path.abspath
oros.path.realpath