I have truly tried my best to understand python imports, but it makes no sense to me. I know there's a million SO threads on this but none of them have helped me understand what's going on.
I have this simple structure:
project/
run.py
datasets/
__init__.py
config.py
datasetA.py
datasetA.py:
from config import classes
dosomething()
run.py:
from datasets import datasetA
And when I execute run.py, I get ModuleNotFoundError: No module named 'config'. Why? I have tried to include
import datasetA
import config
as well as
import .datasetA
import .config
in __init__.py but it makes no difference. datasetA sees __package__ = datasets, so it I think it should see config. run.py sees __package__ = None. What am I missing?
1 Answer 1
Relative vs absolute imports
Your issue relates to the differences between relative and absolute imports. When you try to import config from datasetA, python looks in the root directory, in this case, project/. To fix this, what you want to do is use a relative import in datasetA. See the difference between the following:
# project/datasets/datasetA.py
# Absolute import
from config import classes
# Python checks for an available import at the root of the project
# (e.g. project/ in this case) and fails as it does not exist
# Relative import
from .config import classes
# Python checks in the current directory
# (e.g. project/datasets/) and succeeds
You can read more about relative and absolute imports here
6 Comments
python run.py from the project's root folder, therefore config.classes is actually from datasets.config import classes or relative from .datasets.config import classes. What I mean is that the top level script is not project but run.__main__datasetA.py. I will update my answer accordingly__name__ == '__main__', and all relative imports are relative to the folder the script is being invoked from the interpreter.from datasets.config import classes. When the program runs as a module or package, then everything changes.
datasetA.py, you should have writtenfrom datasets.config import classes. Remember,config.pyis inside a subdirectory, not on project root.run.pyand how do you intend to execute it in the futurefrom .config import classesindatasetA.pyand runpython run.pywhile in theprojectfolder, then even in the filedatasetA.pyyou need to usefrom datasets.config import classes. See my comments on isaa_ctaylor answer. If you look at the traceback you'll see that the ModuleImportError happens when you try to import config from thedatasetA.pyfile, but since your top level module isrun.__main__, config is really datasets.config in every file.