Search code examples
pythonpylint

ImportError : Attempted relative import with no known parent package


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.

My Project Directory

.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

Solution

  • It seems, from Python docs and experimenting, that relative imports (involving ., .. etc) only work if

    1. the importing module has a __name__ other than __main__, and further,
    2. 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.