ImportError : Attempted relative import with no known parent package
PythonPylintPython Problem Overview
I am learning to program with python and I am having issues with importing from a module in a package. I am usingvisual studio code with Python 3.8.2 64 bit.
.vscode
├── ecommerce
│ ├── __init__.py
│ ├── database.py
│ ├── products.py
│ └── payments
│ ├── __init__.py
│ ├── authorizenet.py
│ └── paypal.py
├── __init__.py
└── main.py
in the ecommerce/products.py
file I have:
#products.py
from .database import Database
p = Database(3,2)
So that I can import the Database
class from the ecommerce/database.py
file. But I get error
ImportError : Attempted relative import with no known parent package
Python Solutions
Solution 1 - Python
Since you are using Python 3.8 version, the imports work a little differently, but I think this should work:
Use either:
from database import Database
#Database is the class
or try:
import database.Database
lastly, this one is very secure and best practice possibly:
from . import Database
# The '.' (dot) means from within the same directory as this __init__.py module grab the Database class.
Solution 2 - Python
It seems, from Python docs and experimenting, that relative imports (involving ., .. etc) only work if
- the importing module has a
__name__
other than__main__
, and further, - the
__name__
of the importing module is pkg.module_name, i.e., it has to be imported from above in the directory hierarchy (to have a parent pkg as part of it's__name__
.)
OR
the importing module is being specified via module syntax that includes a parent pkg as python -m pkg.module
, in which case it's __name__
is still __main__
, so it is being run as a script, yet relative imports will work. Here __package__
is set and used to find the parent package while __name__
is __main__
; more here.
[After all that, it appears that __package__
and sys.path
are key to determining if/how relative imports work. __name__
indicates script or module(i.e., __main__
or module_name
). __package__
indicates where in the package the relative imports occur with respect to, and the top of __package__
needs to be in sys.path
.]
So, continuing with @AmitTendulkar 's example, if you run this as > python main.py
or > python -m main
or > python -m ecommerce.products
from the project root directory, or enter interactive python from that root directory and import main
, or import ecommerce.products
the relative imports in products.py will work.
But if you > python products.py
or > python -m products
from within ecommerce directory, or enter interactive python from that ecommerce directory and import products
they will fail.
It is helpful to add
print("In module products __package__, __name__ ==", __package__, __name__)
etc. in each file to debug.
UPDATE:
How imports work depend on sys.path
and __package__
, not on __name__
.
Issued from /home/jj
, > python sub/mod.py
has a sys.path
, __package__
of /home/jj/sub
, None
-absolute imports of modules in sys.path
work, relative imports fail.
> python -m sub.mod
has sys.path
, __package__
of /home/jj
, sub
-absolute imports of modules in sys.path
work, relative imports work relative to sys.path
+ __package__
.
It is more helpful to add
import sys
print("In module products sys.path[0], __package__ ==", sys.path[0], __package__)
etc. in each file to debug.
Solution 3 - Python
i had a similar issue on Windows, and what helped me was (adapted to your directory):
# local imports
import sys
sys.path.append(r"C:\path\to\your\project")
from ecommerce.database import Database
Solution 4 - Python
Considering the below basic file structure
├── ecommerce
│ ├── __init__.py
│ ├── database.py
| └── products.py
└── main.py
I am assuming you are running python main.py
from the project root.
Here is the text copied from the Python tutorial that explains the basic rule around relative import,
> Note that relative imports are based on the name of the current module. Since the name of the main module is always __main__
, modules intended for use as the main module of a Python application must always use absolute imports.
So the below code will work,
# main.py
import ecommerce.products
# or to use it directly
# from ecommerce.products import my_product
ecommerce.products.my_product()
Your product.py might look like,
# ecommerce/products.py
from .database import Database
def my_product():
p = Database(3, 2)
And database.py will look like below,
# ecommerce/database.py
class Database():
def __init__(self, x, y):
self._x = x
self._y = y
print('Inside DB init')
# Rest of the methods...
You will now get,
> python main.py
Inside DB init
Ideally the __init__.py
file at root is not required as the package name is starting from ecommerce.
You can also run python -m ecommerce.products
command to directly call products.py. But that won't yield any output as we are not calling the my_product() function (only defining it).
Calling python ecommerce/products.py
will not work as the name of the current module will then become __main__
and not ecommerce
. The relative importing only works when used within the current package (so in your main script you always need to import your ecommerce
package).
Solution 5 - Python
To allow the use of relative imports, you need to "turn your code into a package". This means all of 1) putting an __init__.py
in the top directory of your code (in your example .vscode
) and 2) adding the full (absolute) path to the parent directory of the top directory (i.e., the parent of your directory .vscode
) to your PYTHONPATH
and 3) setting the __package__
variable in your Python program to the name of the directory that contains __init__.py
, in your case ".vscode
".
You should then be able to use in ecommerce/products.py
:
from .ecommerce.database import Database
I'm not sure why the dot is in the name .vscode
- is that part of the directory name, or part of the lines in your directory tree? If the latter, replace .vscode
with vscode
above.
Solution 6 - Python
This may seem like a hack but it actually work, this happens because of bad package structure
In you case try importing
from .vs_code.ecommerce import database
Now wherever you want to call the class constructor do this:
database.Database()
you can assign this to a variable and use it.
Solution 7 - Python
Try this...
from ecommerce.database import Database
Solution 8 - Python
Presumably, you make executable the file "products.py", which violates the very concept of packages, the package ceases to be a package and relative import does not work. You must call this outside the package.
Here I am also not sure whether the root directory name can start with a dot like ".vscode".
Solution 9 - Python
try the following
from ecommerce import database