Import from another file inside the same module and running from a main.py outside the module throws an import error

Advertisements

Given the following tree:

├── main.py
└── my_module
    ├── a.py
    ├── b.py
    └── __init__.py

a.py:

def f():
    print('Hello World.')

b.py:

from a import f

def f2():
    f()

if __name__ == '__main__':
    f2()

main.py:

from my_module.b import f2

if __name__ == '__main__':
    f2()

When I run b.py, "Hello World." is printed successfully. However, when I run main.py, I get the following error:

Traceback (most recent call last):
  File "/home/user/main.py", line 1, in <module>
    from my_module.b import f2
  File "/home/user/my_module/b.py", line 1, in <module>
    from a import f
ModuleNotFoundError: No module named 'a'

I would expect the same output executing main.py and b.py

>Solution :

Because you have an __init__.py file in the my_module directory, Python sees the entirety of my_module as a package. That also means that all imports within my_module must be relative imports.

This is easily fixed by changing your import in b.py to be a relative import.

b.py

from .a import f

def f2():
    f()

if __name__ == '__main__':
    f2()

If you want to be able to run b.py as a separate script in addition to importing it as part of the the my_module package. You can make the imports conditionally relative or absolute based on whether __name__ == "__main__"

if __name__ != '__main__':
    from .a import f

def f2():
    f()

if __name__ == '__main__':
    from a import f
    f2()

See also the definitive explanation of relative imports on SO

Leave a ReplyCancel reply