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