Cambios en la declaración de importación python3

177

No entiendo lo siguiente de pep-0404

En Python 3, las importaciones relativas implícitas dentro de los paquetes ya no están disponibles; solo se admiten importaciones absolutas e importaciones relativas explícitas. Además, las importaciones en estrella (por ejemplo, desde x import *) solo se permiten en el código de nivel de módulo.

¿Qué es una importación relativa? ¿En qué otros lugares se permitió la importación de estrellas en python2? Por favor explique con ejemplos.

balki
fuente

Respuestas:

277

La importación relativa ocurre cada vez que importa un paquete relativo al script / paquete actual.

Considere el siguiente árbol, por ejemplo:

mypkg
├── base.py
└── derived.py

Ahora, tu derived.pyrequiere algo de base.py. En Python 2, podría hacerlo así (en derived.py):

from base import BaseThing

Python 3 ya no admite eso, ya que no es explícito si desea el 'relativo' o 'absoluto' base. En otras palabras, si hubiera un paquete de Python llamado baseinstalado en el sistema, obtendría el incorrecto.

En cambio, requiere el uso de importaciones explícitas que especifiquen explícitamente la ubicación de un módulo en forma de ruta. Tu derived.pyse vería así:

from .base import BaseThing

El encabezado .dice 'importar basedesde el directorio del módulo'; en otras palabras, .basemapas a ./base.py.

Del mismo modo, hay un ..prefijo que sube la jerarquía del directorio como ../(con ..modasignación a ../mod.py), y luego ...que sube dos niveles ( ../../mod.py) y así sucesivamente.

Sin embargo, tenga en cuenta que las rutas relativas enumeradas anteriormente eran relativas al directorio donde derived.pyreside el módulo ( ) actual , no el directorio de trabajo actual.


@BrenBarn ya ha explicado el caso de importación estrella. Para completar, tendré que decir lo mismo;).

Por ejemplo, necesita usar algunas mathfunciones, pero solo las usa en una sola función. En Python 2 se te permitía ser semi perezoso:

def sin_degrees(x):
    from math import *
    return sin(degrees(x))

Tenga en cuenta que ya activa una advertencia en Python 2:

a.py:1: SyntaxWarning: import * only allowed at module level
  def sin_degrees(x):

En el código moderno de Python 2 debe hacerlo y en Python 3 debe hacer lo siguiente:

def sin_degrees(x):
    from math import sin, degrees
    return sin(degrees(x))

o:

from math import *

def sin_degrees(x):
    return sin(degrees(x))
Michał Górny
fuente
14

Para importaciones relativas ver la documentación . Una importación relativa es cuando importa desde un módulo en relación con la ubicación de ese módulo, en lugar de desde absolutamente sys.path.

En cuanto a import *, Python 2 permitió la importación de estrellas dentro de las funciones, por ejemplo:

>>> def f():
...     from math import *
...     print sqrt

Se emite una advertencia para esto en Python 2 (al menos versiones recientes). En Python 3 ya no está permitido y solo puede realizar importaciones estrella en el nivel superior de un módulo (no dentro de funciones o clases).

BrenBarn
fuente
66
¿Por qué se tomó esa decisión?
Dor
1
Supongo que la idea detrás de esto es "explícito es mejor que implícito". de PEP20 - El zen de Python. El punto antes del módulo hace explícita la vinculación relativa / no relativa, resolviendo así posibles colisiones de nombres. Aunque "la legibilidad cuenta". sufre un poco
Pafnucy
2
No, de hecho fue la decisión "opuesta", "la practicidad vence a la pureza". Eso era necesario para optimizar el acceso a las variables locales dentro de las funciones, ya que sin "import *", el compilador siempre sabe simplemente analizando el código, qué variables son locales y se pueden buscar directamente. De hecho, las funciones ni siquiera usan un dict para el almacenamiento local, sino una matriz optimizada donde las variables obtienen índices únicos.
Veky
11

Para admitir Python 2 y Python 3, use importaciones relativas explícitas como se muestra a continuación. Son relativos al módulo actual. Han sido compatibles a partir de 2.5 .

from .sister import foo
from . import brother
from ..aunt import bar
from .. import uncle
Akseli Palén
fuente
14
import .brother me da un error de sintaxis no válido en Python 3.5. ¿Esto es normal? Tengo init .py en el directorio en el que está
Frikster
1
import .brotheres una sintaxis no válida para python 2 y 3
Rodrigo E. Principe
@ RodrigoE.Principe y así parece ser import ..uncle. Fijo. ¡Oh, qué he estado pensando ... probablemente se distrajo con los caballeros que dicen Ni!
Akseli Palén
4

Se agregó otro caso a la respuesta de Michał Górny:

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 módulo principal de una aplicación Python siempre deben usar importaciones absolutas.

Panfeng Li
fuente