I tried reading other similar questions but the answers didn't work for me, like Python submodule imports using __init__.py and module has no attribute
I have a folder structure like so:
python_scripts
├── lib
│ ├── __init__.py # import lib.talk
│ └── talk.py # def sayhello(x): print(x)
│
├── src
│ ├── __init__.py # import lib.talk
│ └── data
│ ├── __init__.py # import lib.talk
│ └── main.py # from lib.talk import sayhello
│ sayhello('hi')
│
└── __init__.py # import lib.talk
This throws an error:
Traceback (most recent call last):
File "main.py", line 1, in <module>
from lib.talk import sayhello
ModuleNotFoundError: No module named 'lib.talk'
The strange thing is if I simply 'import lib' in main.py there is no error. How should I solve this?
I am using Windows and I would highly prefer to avoid using the sys.path method because we don't want to hardcode the path in (this may be used by other teams in the future).
2 Answers 2
In your main.py file, add following on the top.
import sys
path = r'{path_to_python_scripts}'
if path not in sys.path:
sys.path.append(path)
# Now import
import lib
or
import sys, os
path = os.path.abspath('../..')
if path not in sys.path:
sys.path.append(path)
# Now import
import lib
1 Comment
Use from ...lib import talk. Your import lib.talk doesn't work since lib is a package because of __init__.py inside lib dictionary.
You can also use path appending way, but you need to get it something like this:
import os, sys
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..', 'libs')))
This way you will always append path to libs dynamically no matter where your Python code is stored.
4 Comments
main.py should be in the main directory, so all imports from subdirectory/subpackage will be relative to this script. At your solution, you need to go up over your directory tree and also other people will have a problem to find main.py.data folder should be only for storing data. No Python files inside. Data parser should be inside lib and main.py should in the main directory. This way when you import parser from lib directory into main, path to data directory still be relative to main.py. It's easier to maintain.