438

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:

  1. test.py
  2. 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. :)

11
  • 2
    I cannot reproduce the error, how do you execute this code? Commented May 5, 2017 at 1:57
  • 3
    I 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 Commented May 5, 2017 at 4:03
  • 2
    Very 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!
    – blitzmann
    Commented May 5, 2017 at 5:17
  • 2
    My guess is that something funky is going on with PYTHONPATH. Check your IDE settings and/or system environment variables. Commented May 6, 2017 at 19:53
  • 4
    I 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.
    – user3159377
    Commented Aug 7, 2017 at 21:14

19 Answers 19

340
+25

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.

9
  • 7
    Is 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 ?
    – James T.
    Commented Dec 7, 2017 at 19:22
  • 8
    @JamesT. Yes, it's pretty common to modify sys.path during runtime (github.com/…). You can also set PYTHONPATH environment variable.
    – Igonato
    Commented Dec 8, 2017 at 4:32
  • 14
    "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.
    – Kevin
    Commented May 7, 2019 at 16:48
  • 4
    "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.
    – smci
    Commented May 8, 2019 at 3:09
  • thanks 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?
    – torez233
    Commented Jun 14, 2021 at 1:26
166

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

5
  • 7
    Huge thanks @Giorgos! This is especially true when you're trying to set a root directory in a docker image. Commented Aug 7, 2019 at 21:18
  • 1
    This worked for me instead, on Ubuntu: export PYTHONPATH="/home/me/projects/foo:$PYTHONPATH" Commented Jan 16, 2023 at 11:21
  • So we have to append our project's path to PYTHONPATH regardless of how we structure our project? Commented Dec 18, 2023 at 5:52
  • 2
    pls dont point us to the article that require subscription,
    – junnyea
    Commented Feb 7 at 2:05
  • As last comment, don't post articles with restrictions here, that is quite annoying. Commented Jun 21 at 17:20
119

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
6
  • 3
    Worth noting that the try/except loading procedure is the real ingredient that works here (as some people will need to use try:scripts.modx and except: modx), and was what solved this issue for me. Commented Mar 1, 2020 at 23:09
  • Try/except on import is ugly. I wish there was a better solution.
    – ingyhere
    Commented Aug 10, 2020 at 15:30
  • 5
    You 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. Commented Sep 13, 2020 at 19:05
  • 1
    thank you so much! this dot (.) was the actual problem for me =)
    – Aidos
    Commented Jun 14, 2021 at 11:21
  • 1
    I am using a library called generateDS and I add a dot at the module name and solve the problem in 2021! Thanks!
    – etoricky
    Commented Oct 6, 2021 at 11:03
65

Setting PYTHONPATH can also help with this problem.

Here is how it can be done on Windows

set PYTHONPATH=.

3
  • 14
    setting PYTHONPATH to main code directory solved the problem for me!
    – Geek
    Commented May 22, 2018 at 4:21
  • 9
    Works in Linux as well. export PYTHONPATH=.
    – rjdkolb
    Commented Mar 3, 2020 at 6:01
  • 1
    Works on MacOs as well. export PYTHONPATH=.
    – Thales
    Commented Jan 18, 2023 at 13:17
29

You can simply add following file to your tests directory, and then python will run it before the tests

__init__.py file

import os
import sys
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
3
  • 1
    This is what I was exactly looking for. Thanks for sharing this answer!!!
    – Mayur
    Commented Jun 10, 2019 at 5:48
  • 1
    Doing 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)
    – Sharad
    Commented Feb 5, 2020 at 23:32
  • Excellent. These contents for the __init__ file work in Python 3.6.6
    – VISQL
    Commented Jan 31, 2021 at 20:48
20

Set PYTHONPATH environment variable in root project directory.

Considering UNIX-like:

export PYTHONPATH=.
0
18

If you are using python 3+ then try adding below lines

import os, sys
dir_path = os.path.dirname(os.path.realpath(__file__))
parent_dir_path = os.path.abspath(os.path.join(dir_path, os.pardir))
sys.path.insert(0, parent_dir_path)
1
  • 3
    Another 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 or os.path.realpath Commented Jun 23, 2022 at 10:48
15

Tried your example

from . import config

got the following SystemError:
/usr/bin/python3.4 test.py
Traceback (most recent call last):
File "test.py", line 1, in
from . import config
SystemError: Parent module '' not loaded, cannot perform relative import


This will work for me:

import config
print('debug=%s'%config.debug)

>>>debug=True

Tested with Python:3.4.2 - PyCharm 2016.3.2


Beside this PyCharm offers you to Import this name.
You hav to click on config and a help icon appears. enter image description here

10

Declare correct sys.path list before you call module:

import os, sys

#'/home/user/example/parent/child'
current_path = os.path.abspath('.')

#'/home/user/example/parent'
parent_path = os.path.dirname(current_path)

sys.path.append(parent_path)
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'child.settings')
8

I am working in a Linux machine. I had the same issue when I run python my_module/__main__.py.

The error is fixed, if you run the command export PYTHONPATH=. before your run your script.

export PYTHONPATH=.
python my_module/__main__.py
7

Try

from . import config

What that does is import from the same folder level. If you directly try to import it assumes it's a subordinate

4

This example works on Python 3.6.

I suggest going to Run -> Edit Configurations in PyCharm, deleting any entries there, and trying to run the code through PyCharm again.

If that doesn't work, check your project interpreter (Settings -> Project Interpreter) and run configuration defaults (Run -> Edit Configurations...).

4

You may use these statements to set the working directory, which worked for me with python3

import os
import sys
sys.path.insert(1, os.getcwd())
3

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 :)

2
  • 2
    Hmm 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)
    – naoko
    Commented Aug 1, 2017 at 19:27
  • 2
    Different 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.
    – winux
    Commented Dec 12, 2018 at 8:41
1

For me, simply adding the current directory worked.

Using the following structure:

└── myproject
    ├── a.py
    └── b.py

a.py:

from b import some_object
# returns ModuleNotFound error

from myproject.b import some_object
# works
1

I see many answers importing sys and os. Here's a not mentioned yet shorter one that GitHub Copilot gave me:

import sys

sys.path.append(__file__.rsplit("/", 1)[0])

Adding this to the top of my python script solved the problem as well.

0

In my experience, PYTHONPATH environment variable does not work everytime.

In my case, my pytest only worked when I added the absolute path: sys.path.insert( 0, "/Users/bob/project/repo/lambda" )

2
  • don't forget import sys :) Commented Feb 10, 2022 at 15:13
  • 2
    As 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.
    – Community Bot
    Commented Feb 10, 2022 at 17:04
0

To have Bash automatically recognise the project dir you're in:

sudo nano ~/.bashrc

OR

sudo nano ~/.bash_profile

At the bottom of the bash file:

function set_pythonpath {
    export PYTHONPATH="$(pwd):$PYTHONPATH"
}

PROMPT_COMMAND=set_pythonpath

To save and exit:

  • Ctrl + X
  • Y

Test your changes by:

cat ~/.bashrc
0

The existing answers do well to explain the possible causes of the issue. For those cases where the Exception results from attempted relative imports, I find the following approach can help resolve:

  1. Search project files for from .
  2. Update all those imports to absolute imports
  3. Use absolute imports for all new imports

It's a pain, and less flexible, but helps avoid circular-import-caused errors.

Another common, albeit less-common, cause for these issues in my experience is conflicting namespaces. This error tends to be the most insidious to debug as there is rarely an indication of conflicts in error messaging.

In almost all cases, it takes manual context-specific debugging. However, general example would be:

.
└── root/
    ├── apps/
    │   ├── ...
    |   |── app2/
    │   └── app2/
    │       ├── ...
    │       └── main.py
    └── venv/
        ├── ...
        └── Lib/
            └── site-packages/
                ├── ...
                └── django/
                    ├── ...
                    └── apps

In the root/apps/app1/main.py file, imagine you import something from apps.app2 and also try from django.apps. That will cause an issue in most cases because apps enters the namespace from two locations.

However, the error message is usually something that leads one to believe it's a circular import a imports b and b imports a when really it's confusion over what a and b really are.

Not the answer you're looking for? Browse other questions tagged or ask your own question.