Alejo Dev
Alejo Dev

Reputation: 2586

Python ModuleNotFoundError when executing script directly

I have browsed over a lot of questions on this topic, and I have found a lot of information, but I am still unable to fully understand what is happening and how to solve my problem

This is the question:

I am using python3.9.5, and I have the following layout:

root_folder/
    src/
       a.py
       b.py

Inside a.py I have:

from src.b import do_something_B

def do_something_A():
    do_something_B()

if __name__ == '__main__':
    do_something_A()

An b.py:

def do_something_B():
    print("Hello from B")

If I run Ipython REPL, I can do:

from src.a import do_something_A
do_something_A() # this prints "Hello from B" without errors

But if I try to execute a.py from console I get the following output:

❯ python src/a.py 
Traceback (most recent call last):
  File "/home/alejo/playground/root_folder/src/a.py", line 1, in <module>
    from src.b import do_something_B
ModuleNotFoundError: No module named 'src'

Creating a __init__.py file inside src folder does not make any difference

What am I understanding wrong?

EDIT

If I change a.py to import b without src namespace (changing first line to from b import do_something_B) then I can execute the script from bash, but it fails when I try to use it with iPython REPL

Upvotes: 0

Views: 617

Answers (2)

Alejo Dev
Alejo Dev

Reputation: 2586

I found the answer to my own question browsing the documentation:

Quoting https://docs.python.org/3/tutorial/modules.html#the-module-search-path

When a module named spam is imported, the interpreter first searches for a built-in module with that name. If not found, it then searches for a file named spam.py in a list of directories given by the variable sys.path. sys.path is initialized from these locations:

  • The directory containing the input script (or the current directory when no file is specified).

  • PYTHONPATH (a list of directory names, with the same syntax as the shell variable PATH).

  • The installation-dependent default.

As I am specifiying an script, the folder of the script is added to sys.path, not the current folder

I would need to add a c.py file directly in root_folder than imports src.a and executes do_something_A() to be able to call it from bash

Upvotes: 0

Miles B
Miles B

Reputation: 129

You don't need to specify the directory as the two files are in the same directory already.

Simply do from b import do_something_B and it should work.

Same thing in b.py

Also to clarify, using src.someFunc implies that there is a module named src not that there is a directory named src.

Look into absolute imports if you need to import across directories, which in this case you do not, so don't worry.

Upvotes: 1

Related Questions