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
It seems, from Python docs and experimenting, that relative imports (involving., .. etc) only work if
__name__
other than __main__
, and further,__name__
of the importing module is pkg.module_name, ie, 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(ie, __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.
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.
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
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).
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 (ie, 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.
Try this...
from ecommerce.database import Database
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.
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".
尝试以下
from ecommerce import database
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
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.