412

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

wjandrea
  • 28,235
  • 9
  • 60
  • 81
blitzmann
  • 7,319
  • 5
  • 23
  • 29
  • 2
    I cannot reproduce the error, how do you execute this code? – Copperfield May 05 '17 at 01:57
  • I execute `test.py` through pyCharm with Python 3.6. Does yours execute fine? – blitzmann May 05 '17 at 03:18
  • 2
    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 – Copperfield May 05 '17 at 04: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 May 05 '17 at 05:17
  • 2
    My guess is that something funky is going on with PYTHONPATH. Check your IDE settings and/or system environment variables. – Martin Tournoij May 06 '17 at 19:53
  • 3
    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. –  Aug 07 '17 at 21:14
  • sys.path.append(r'C:/.../LastFolder') works all the time – ParaH2 Aug 10 '18 at 20:43
  • If I run it from console first option works for me and second gives me "ImportError: attempted relative import with no known parent package". – mrgloom Jan 04 '22 at 13:15
  • I think[,](https://semicolon.dev/python/how-to-fix-modulenotfounderror-no-module-named) it's because you are doing a relative import. Best to use absolute paths, here is a [medium article](https://towardsdatascience.com/how-to-fix-modulenotfounderror-and-importerror-248ce5b69b1c) that explains in detail how to do that[.](https://www.youtube.com/watch?v=6zr73ZeLK4I) and why exactly this error occurs. – InfiniteStack Aug 14 '22 at 19:08
  • For those using VS Code, [this](https://stackoverflow.com/questions/62366211/vscode-modulenotfounderror-no-module-named-x) answer solved it for me. – user Aug 06 '23 at 16:40

19 Answers19

323

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.

iron9
  • 397
  • 2
  • 12
Igonato
  • 10,175
  • 3
  • 35
  • 64
  • 5
    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. Dec 07 '17 at 19:22
  • 5
    @JamesT. Yes, it's pretty common to modify `sys.path` during runtime (https://github.com/search?q=sys.path.append&type=Code&utf8=%E2%9C%93). You can also set PYTHONPATH environment variable. – Igonato Dec 08 '17 at 04:32
  • 13
    "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 May 07 '19 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?](https://stackoverflow.com/questions/448271/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 May 08 '19 at 03: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 Jun 14 '21 at 01:26
  • What is "part of a package" here mean? – mrgloom Jan 04 '22 at 13:25
  • What is in the `sys.path` in this example? – mrgloom Jan 04 '22 at 13:25
  • Why we don't import it like "from ryan import config"? – mrgloom Jan 04 '22 at 13:29
146

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

Giorgos Myrianthous
  • 36,235
  • 20
  • 134
  • 156
116

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
  • 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. – Justapigeon Mar 01 '20 at 23:09
  • Try/except on import is ugly. I wish there was a better solution. – ingyhere Aug 10 '20 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. – Giorgos Myrianthous Sep 13 '20 at 19:05
  • 1
    thank you so much! this dot (.) was the actual problem for me =) – Aidos Jun 14 '21 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 Oct 06 '21 at 11:03
  • adding . when importing a file (in my case, from .file1 import my_var) still working great in python 3.7, thank you – altela Feb 14 '22 at 01:07
63

Setting PYTHONPATH can also help with this problem.

Here is how it can be done on Windows

set PYTHONPATH=.

foxtdev
  • 161
  • 1
  • 15
Santosh Pillai
  • 8,169
  • 1
  • 31
  • 27
28

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__), '..')))
Vinod Rane
  • 455
  • 4
  • 4
  • 1
    This is what I was exactly looking for. Thanks for sharing this answer!!! – Mayur Jun 10 '19 at 05: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 Feb 05 '20 at 23:32
  • Excellent. These contents for the `__init__` file work in Python 3.6.6 – VISQL Jan 31 '21 at 20:48
20

Set PYTHONPATH environment variable in root project directory.

Considering UNIX-like:

export PYTHONPATH=.
manasouza
  • 1,189
  • 1
  • 14
  • 26
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

stovfl
  • 14,998
  • 7
  • 24
  • 51
15

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)
Vivek Garg
  • 2,115
  • 1
  • 20
  • 17
  • 2
    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` – Harshad Vyawahare Jun 23 '22 at 10:48
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')
HoangYell
  • 4,100
  • 37
  • 31
6

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

Arny Boy
  • 61
  • 2
  • 10
6

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
Georgios Syngouroglou
  • 18,813
  • 9
  • 90
  • 92
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...).

Carson Crane
  • 1,197
  • 8
  • 15
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 :)

blitzmann
  • 7,319
  • 5
  • 23
  • 29
  • 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 Aug 01 '17 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 Dec 12 '18 at 08:41
3

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())
joydeba
  • 778
  • 1
  • 9
  • 24
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
half of a glazier
  • 1,864
  • 2
  • 15
  • 45
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" )

llincolnatal
  • 81
  • 1
  • 4
  • don't forget `import sys` :) – llincolnatal Feb 10 '22 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](/help/how-to-answer). – Community Feb 10 '22 at 17:04
0

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.

Pablo LION
  • 1,294
  • 6
  • 20
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
DanielBell99
  • 896
  • 5
  • 25
  • 57
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.

alphazwest
  • 3,483
  • 1
  • 27
  • 39