web-dev-qa-db-fra.com

Quel est le problème avec les importations relatives en Python?

J'ai récemment mis à jour des versions de pylint , un populaire vérificateur de style Python.

Il est devenu balistique tout au long de mon code, indiquant les endroits où j'importe des modules dans le même package, sans spécifier le chemin complet du package.

Le nouveau message d'erreur est W0403.

W0403: Importation relative% r, doit être% r

Utilisé lorsqu'une importation relative au répertoire du package est détectée.


Exemple

Par exemple, si mes packages sont structurés comme ceci:

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

et dans le paquet éponge j'écris:

import icing

au lieu de

import cake.icing

J'obtiendrai cette erreur.


Bien que je comprenne que tous les messages Pylint n'ont pas la même importance et que je n'ai pas peur de les rejeter, je ne comprends pas pourquoi une telle pratique est considérée comme une mauvaise idée.

J'espérais que quelqu'un pourrait expliquer les pièges, afin que je puisse améliorer mon style de codage plutôt que (comme je prévois actuellement de le faire) de désactiver cet avertissement apparemment faux.

92
Oddthinking

Le problème de import icing est que vous ne savez pas s'il s'agit d'une importation absolue ou d'une importation relative. icing pourrait un module dans le chemin de python, ou un package dans le module actuel. C'est assez ennuyeux lorsqu'un package local porte le même nom qu'un package de bibliothèque standard python.

Tu peux faire from __future__ import absolute_import qui désactive complètement les importations relatives implicites. Il est décrit, y compris avec cette justification de l'ambiguïté, dans PEP 328 . Je crois que Python 3000 a des importations relatives implicites complètement désactivées.

Vous pouvez toujours faire des importations relatives, mais vous devez les faire explicitement, comme ceci:

from . import icing
101
Winston Ewert

Il y a quelques bonnes raisons:

  1. Les importations relatives se cassent facilement lorsque vous déplacez un module.

    Imaginez que vous avez un foo.bar, une foo.baz et un module baz dans votre package. foo.bar importe foo.baz, mais en utilisant une importation relative.

    Maintenant, si vous déménagiez foo.bar à bar, votre module importe soudainement un autre baz!

  2. Les importations relatives sont ambiguës. Même sans se déplacer dans le module bar dans l'exemple ci-dessus, un nouveau développeur venant à votre projet pourrait être pardonné de ne pas se rendre compte que baz est vraiment foo.baz au lieu du package de niveau racine baz.

    Les importations absolues indiquent clairement quel module est utilisé. Et comme import this prêche, explicite vaut mieux qu'implicite.

  3. Python 3 a complètement désactivé les importations relatives implicites; les importations sont désormais toujours interprétées comme absolues, ce qui signifie que dans l'exemple ci-dessus import baz importera toujours le module de niveau supérieur. Vous devrez utiliser la syntaxe d'importation explicite à la place (from . import baz).

    Porter l'exemple de Python 2 à 3 entraînerait donc des problèmes inattendus, l'utilisation des importations absolues maintenant rendra votre code à l'épreuve du temps.

49
Martijn Pieters