¿Qué hay de malo con las importaciones relativas en Python?

87

Recientemente actualicé versiones de pylint , un popular comprobador de estilo de Python.

Se ha ido balístico a lo largo de mi código, señalando los lugares donde importo módulos en el mismo paquete, sin especificar la ruta completa del paquete.

El nuevo mensaje de error es W0403.

  

W0403: la importación relativa% r, debe ser% r

     

Se utiliza cuando se detecta una importación relativa al directorio del paquete.

Ejemplo

Por ejemplo, si mis paquetes están estructurados de esta manera:

/cake
  /__init__.py
  /icing.py
  /sponge.py
/drink

y en el paquete de esponja escribo:

import icing

en lugar de

import cake.icing

Obtendré este error.

Si bien entiendo que no todos los mensajes de Pylint tienen la misma importancia, y no temo descartarlos, no entiendo por qué esta práctica se considera una mala idea.

Tenía la esperanza de que alguien pudiera explicar las dificultades, para poder mejorar mi estilo de codificación en lugar de (como tengo previsto hacerlo) desactivar esta advertencia aparentemente falsa.

    
pregunta Oddthinking 04.08.2012 - 17:29

2 respuestas

93

El problema de import icing es que no se sabe si es una importación absoluta o una importación relativa. icing podría un módulo en la ruta de acceso de python, o un paquete en el módulo actual. Esto es bastante molesto cuando un paquete local tiene el mismo nombre que un paquete de biblioteca estándar de Python.

Puede hacer from __future__ import absolute_import que desactiva las importaciones relativas implícitas. Se describe, incluida esta justificación sobre la ambigüedad, en PEP 328 . Creo que Python 3000 tiene las importaciones relativas implícitas desactivadas por completo.

Todavía puedes hacer importaciones relativas, pero tienes que hacerlo explícitamente, como esto:

from . import icing
    
respondido por el Winston Ewert 04.08.2012 - 17:36
47

Hay algunas buenas razones:

  1. Las importaciones relativas se rompen fácilmente cuando mueves un módulo.

    Imagina que tienes un módulo foo.bar , un foo.baz y un módulo baz en tu paquete. foo.bar importa foo.baz , pero utilizando una importación relativa.

    Ahora, si moviera foo.bar a bar , ¡su módulo de repente está importando un baz diferente!

  2. Las importaciones relativas son ambiguas. Incluso sin moverse por el módulo bar en el ejemplo anterior, se podría perdonar a un nuevo desarrollador que venga a su proyecto por no darse cuenta de que baz es realmente foo.baz en lugar del paquete baz de nivel raíz.

    Las importaciones absolutas hacen que sea explícito qué módulo se está utilizando. Y como import this predica, explícito es mejor que implícito.

  3. Python 3 ha deshabilitado las importaciones relativas implícitas por completo; las importaciones ahora siempre se interpretan como absolutas, lo que significa que en el ejemplo anterior import baz siempre importará el módulo de nivel superior. Deberá usar la sintaxis de importación explícita en su lugar ( from . import baz ).

    Portar el ejemplo de Python 2 a 3 provocaría problemas inesperados, ya que el uso de importaciones absolutas hará que su código esté preparado para el futuro.

respondido por el Martijn Pieters 04.08.2012 - 17:43

Lea otras preguntas en las etiquetas