Module can't find a module in the same folder

Question:

I have a directory structure like this:

project
|    baz.py
|
|____pack1
|    |
|    |   foobar.py
|    |   test1.py
|    |
|

Content of test1.py is:
import foobar

Content of baz.py is :
from pack1 import test1

When I run test1.py, it imports foobar without a problem.
But when I run baz.py, it throws an exception:

ModuleNotFoundError: No module named 'foobar'

Why is this happening and how can fix it?

Asked By: Kamal 37

||

Answers:

To make it simple, This is because baz.py won’t get foobar.py module directly from test1.py.


Whenever baz.py reads import foobar inside test1.py, it wants to import it separately (not to be dependent on test1.py), that is why you get this error.
to solve it, you can type from pack1 import foobar inside test1.py , So baz.py
reads from pack1 import foobar instead of import foobar.

Answered By: Dark Dragon

When you run the test1.py script, it works because Python will add the script’s directory automatically to sys.path (which contains the directories to be searched during imports):

[…] As initialized upon program startup, the first item of this list, path[0], is the directory containing the script that was used to invoke the Python interpreter. […]

So when import foobar is encountered, it will successfully search the directory project/pack1 since that is the directory which also contains the test1.py script.

However, when you run baz.py, since it resides in another directory, project/pack1 is never added to sys.path and thus foobar.py cannot be found.

You can fix this by using the following import statement in test1.py:

from . import foobar

This tells Python that the foobar module is located inside the same package as the importing module (i.e. test1 in this case). Now running python baz.py should work.

However, when you try to run python pack1/test1.py now, there should be an error similar to:

[...]
    from . import foobar
ImportError: attempted relative import with no known parent package

This is because when you run python pack1/test1.py directly, is has no information about the package that contains the test1 module. You can fix this by invoking the script with the -m switch:

/path/to/project$ python -m pack1.test1
/path/to/project$ python baz.py

Both of the above should work now.

Answered By: a_guest
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.