La opción de línea de comando -m permite ejecutar un módulo como si fuera un programa. Cuando se ejecuta así un módulo que está dentro de un paquete, las importaciones relativas no funcionaban correctamente. Las importaciones relativas permiten a un módulo importar otros módulos dentro de un paquete usando rutas relativas, lo que permite cambiar la ubicación de todo el paquete a otra rama del sistema de directorio sin problemas.
Este error se ha corregido en Python 2.6 añadiendo un atributo __package__ a los módulos. Si este atributo está definido en el módulo, las importaciones relativas se realizarán en relación a su valor, en vez de al valor del atributo __name__.
Los importadores definidos según la PEP 302 pueden definir el atributo __package__ como crean necesario. El módulo runpy, que implementa la opción -m ya lo hace, de modo que si tenías módulos que actuaban también como programas y hacían uso de la importación relativa, ahora funcionan. Este cambio no implica, por lo tanto, ningún problema para la migración de nuestro código.
Importaciones relativas
Para ampliar un poco el tema de las importaciones relativas, añado un extracto del PEP-328 (Imports: Multi-Line and Absolute/Relative).
Después de una interesante y amplia discusión, se ha aceptado que los imports relativos usarán puntos como prefijos para indicar los niveles de anidamiento. Un único punto indica que es un import relativo, y se refiere al nivel actual. Dos o más puntos indican padres y demás ascendientes del nivel actual, indicando cada nivel con un punto. Por ejemplo, si tuviéramos la siguiente estructura en nuestro paquete (con perdón):
package/ __init__.py subpackage1/ __init__.py moduleX.py moduleY.py subpackage2/ __init__.py moduleZ.py moduleA.py
Y suponiendo que el fichero actual es moduleX.py o subpackage1/__init__.py, los siguientes ejemplos de importación relativa son válidos:
from .moduleY import spam from .moduleY import spam as ham from . import moduleY from ..subpackage1 import moduleY from ..subpackage2.moduleZ import eggs from ..moduleA import foo from ...package import bar from ...sys import path
Obsérvese que, aunque el último ejemplo es válido, está claramente desaconsejado (Guido lo definió como "chaladura").
Las importaciones relativas siempre deben usar la forma from X import; la forma import X siempre es absoluta. También debe quedar claro que se puede seguir haciendo importaciones absolutas con la primera forma, solo hay que excluir los puntos prefijos.
Ver comentarios