Getting "ImportError: attempted relative import with no known parent package" when running from Python Interpreter
I know I'm late to the party, but I think I've found a solution to this problem. Hopefully this will be useful to someone else working on a large Python project.
The trick is to try one import format and fall back to the other format if the first fails.
Approach 1
db.py
try:
# Assume we're a sub-module in a package.
from . import models
except ImportError:
# Apparently no higher-level package has been imported, fall back to a local import.
import models
On the plus side, this approach is pretty simple, but doesn't scale well (module names are duplicated). Scaling can be improved by importing programmatically.
Approach 2 (not recommended)
db.py
import importlib
root = 'project.modules.core'
my_modules = ['core', 'models']
for m in my_modules
try:
globals()[m] = importlib.import_module(root + '.' + m)
except ImportError:
globals()[m] = importlib.import_module(m)
globals() is the global symbol table.
Of course, now this functionality needs to be duplicated in every module. I'm not sure that's actually an improvement over the first approach. However, you can separate this logic out into its own independent package that lives somewhere on pythonpath.
Approach 3
package_importer.py
import importlib
def import_module(global_vars, root, modules):
for m in modules
try:
global_vars[m] = importlib.import_module(root + '.' + m)
except ImportError:
global_vars[m] = importlib.import_module(m)
db.py
import package_importer
root = 'project.modules.core'
my_modules = ['core', 'models']
package_importer.import_module(globals(), root, my_modules)
This may be a bit outdated, but maybe someone else will benefit of my answer. Since python2 und python3 have different default import behavior, you have to determine between these two python versions.
Python 2.X
The default behavior for import models
is to look up first the relative and then the absolute search path order. Therefore it should work.
However, in Python 3.X the default behavior for import models
is to look for the model only in the absolute paths (called absolute imports). The current package core gets skipped and since the module db cannot be found anywhere else in the sys.path search path, it throws an error. To resolve this issue you have to use the import statement with dots from . import models
to make clear that you are trying to import from a relative directory.
If you are interested to learn more about importing python modules, I suggest you to start your research with the following key words: module search path, python package import and relative package imports