Estoy aprendiendo a programar con python y tengo problemas para importar desde un módulo en un paquete. Estoy usando el código de Visual Studio con Python 3.8.2 de 64 bits.
.vscode ├── ecommerce │ ├── __init__.py │ ├── database.py │ ├── products.py │ └── payments │ ├── __init__.py │ ├── authorizenet.py │ └── paypal.py ├── __init__.py └── main.py en el archivo ecommerce/products.py tengo:
#products.py from .database import Database p = Database(3,2) Para que pueda importar la clase de Database de datos desde el archivo ecommerce/database.py . pero me sale error
ImportError : Attempted relative import with no known parent packageDado que está utilizando la versión Python 3.8, las importaciones funcionan de manera un poco diferente, pero creo que esto debería funcionar:
Utilizar cualquiera:
from database import Database #Database is the classo tratar:
import database.Databasepor último, este es muy seguro y posiblemente la mejor práctica:
from . import Database # The '.' (dot) means from within the same directory as this __init__.py module grab the Database class.Esto puede parecer un truco, pero en realidad funciona, esto sucede debido a una mala estructura del paquete.
En tu caso intenta importar
from .vs_code.ecommerce import database
Ahora, donde quiera que quiera llamar al constructor de clase, haga esto:
database.Database()
puede asignar esto a una variable y usarlo.
prueba lo siguiente
from ecommerce import databasePrueba esto...
from ecommerce.database import DatabasePresuntamente, haces ejecutable el archivo "products.py", lo que viola el concepto mismo de paquetes, el paquete deja de ser un paquete y la importación relativa no funciona. Debe llamar a esto fuera del paquete.
Aquí tampoco estoy seguro de si el nombre del directorio raíz puede comenzar con un punto como ".vscode".
tuve un problema similar en Windows, y lo que me ayudó fue (adaptado a su directorio):
# local imports import sys sys.path.append(r"C:\path\to\your\project") from ecommerce.database import DatabaseTeniendo en cuenta la siguiente estructura básica de archivos
├── ecommerce │ ├── __init__.py │ ├── database.py | └── products.py └── main.py Supongo que está ejecutando python main.py desde la raíz del proyecto.
Aquí está el texto copiado del tutorial de Python que explica la regla básica sobre la importación relativa,
Tenga en cuenta que las importaciones relativas se basan en el nombre del módulo actual. Dado que el nombre del módulo principal siempre es
__main__, los módulos destinados a usarse como el módulo principal de una aplicación de Python siempre deben usar importaciones absolutas.
Así que el siguiente código funcionará,
# main.py import ecommerce.products # or to use it directly # from ecommerce.products import my_product ecommerce.products.my_product()Su product.py podría verse como,
# ecommerce/products.py from .database import Database def my_product(): p = Database(3, 2)Y base de datos.py se verá como a continuación,
# ecommerce/database.py class Database(): def __init__(self, x, y): self._x = x self._y = y print('Inside DB init') # Rest of the methods...Ahora obtendrás,
> python main.py Inside DB init Idealmente, no se requiere el archivo __init__.py en la raíz, ya que el nombre del paquete comienza con el comercio electrónico.
También puede ejecutar el comando python -m ecommerce.products para llamar directamente a products.py. Pero eso no generará ningún resultado ya que no estamos llamando a la función my_product() (solo definiéndola).
Llamar a python ecommerce/products.py no funcionará ya que el nombre del módulo actual se convertirá en __main__ y no en ecommerce . La importación relativa solo funciona cuando se usa dentro del paquete actual (por lo que en su script principal siempre necesita importar su paquete de ecommerce ).
Parece, según los documentos y la experimentación de Python , que las importaciones relativas (que involucran ., .. etc.) solo funcionan si
__name__ que no __main__ y, además,__name__ del módulo de importación es pkg.module_name, es decir, debe importarse desde arriba en la jerarquía de directorios (para tener un paquete principal como parte de su __name__ ).O
el módulo de importación se especifica a través de la sintaxis del módulo que incluye un paquete principal como python -m pkg.module , en cuyo caso su __name__ sigue siendo __main__ , por lo que se ejecuta como un script, pero las importaciones relativas funcionarán. Aquí __package__ se establece y se utiliza para encontrar el paquete principal, mientras que __name__ es __main__ ; más aquí
[Después de todo eso, parece que __package__ y sys.path son clave para determinar si/cómo funcionan las importaciones relativas. __name__ indica script o módulo (es decir, __main__ o module_name ). __package__ indica en qué lugar del paquete se producen las importaciones relativas, y la parte superior de __package__ debe estar en sys.path .]
Entonces, continuando con el ejemplo de @AmitTendulkar, si ejecuta esto como > python main.py o > python -m main o > python -m ecommerce.products desde el directorio raíz del proyecto, o ingresa python interactivo desde ese directorio raíz e import main , o import ecommerce.products , las importaciones relativas en products.py funcionarán.
Pero si > python products.py o > python -m products desde el directorio de comercio electrónico, o ingresa a python interactivo desde ese directorio de comercio electrónico e import products , fallarán.
Es útil agregar
print("In module products __package__, __name__ ==", __package__, __name__)etc. en cada archivo para depurar.
ACTUALIZAR:
El funcionamiento de las importaciones depende de sys.path y __package__ , no de __name__ . Emitido desde /home/jj , > python sub/mod.py tiene un sys.path , __package__ de /home/jj/sub , None : las importaciones absolutas de módulos en sys.path funcionan, las importaciones relativas fallan.
> python -m sub.mod tiene sys.path , __package__ de /home/jj , las importaciones sub -absolutas de módulos en sys.path funcionan, las importaciones relativas funcionan en relación con sys.path + __package__ .
Es más útil agregar
import sys print("In module products sys.path[0], __package__ ==", sys.path[0], __package__)etc. en cada archivo para depurar.
Para permitir el uso de importaciones relativas, debe "convertir su código en un paquete". Esto significa todo de 1) colocar un __init__.py en el directorio superior de su código (en su ejemplo .vscode ) y 2) agregar la ruta completa (absoluta) al directorio principal del directorio superior (es decir, el principal de su directorio .vscode ) a su PYTHONPATH y 3) configurando la variable __package__ en su programa de Python al nombre del directorio que contiene __init__.py , en su caso " .vscode ".
Entonces debería poder usar en ecommerce/products.py :
from .ecommerce.database import Database No estoy seguro de por qué el punto está en el nombre .vscode . ¿Es eso parte del nombre del directorio o parte de las líneas en su árbol de directorios? Si es lo último, reemplace .vscode con vscode arriba.