it-swarm.com.de

Was ist falsch an relativen Importen in Python?

Ich habe kürzlich Versionen von pylint aktualisiert, einem beliebten Python Style-Checker).

Es ist in meinem gesamten Code ballistisch geworden und weist auf Stellen hin, an denen ich Module in dasselbe Paket importiere, ohne den vollständigen Paketpfad anzugeben.

Die neue Fehlermeldung lautet W0403.

W0403: Relativer Import% r sollte% r sein

Wird verwendet, wenn ein Import relativ zum Paketverzeichnis erkannt wird.


Beispiel

Zum Beispiel, wenn meine Pakete so aufgebaut sind:

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

und in das Schwammpaket schreibe ich:

import icing

anstatt

import cake.icing

Ich werde diesen Fehler bekommen.


Obwohl ich verstehe, dass nicht alle Pylint-Nachrichten gleich wichtig sind und ich keine Angst habe, sie zu verwerfen, verstehe ich nicht, warum eine solche Praxis als schlechte Idee angesehen wird.

Ich hatte gehofft, jemand könnte die Fallstricke erklären, damit ich meinen Codierungsstil verbessern könnte, anstatt (wie ich es derzeit vorhabe) diese scheinbar falsche Warnung auszuschalten.

92
Oddthinking

Das Problem von import icing ist, dass Sie nicht wissen, ob es sich um einen absoluten oder einen relativen Import handelt. icing könnte ein Modul im Python-Pfad oder ein Paket im aktuellen Modul sein. Dies ist ziemlich ärgerlich, wenn ein lokales Paket denselben Namen wie ein Standardbibliothekspaket python) hat.

Du kannst tun from __future__ import absolute_import, wodurch implizite relative Importe insgesamt deaktiviert werden. Es wird, einschließlich dieser Begründung zur Mehrdeutigkeit, in PEP 328 beschrieben. Ich glaube Python 3000 hat implizite relative Importe vollständig deaktiviert.

Sie können weiterhin relative Importe durchführen, müssen diese jedoch explizit wie folgt ausführen:

from . import icing
101
Winston Ewert

Es gibt einige gute Gründe:

  1. Relative Importe können leicht unterbrochen werden, wenn Sie ein Modul verschieben.

    Stellen Sie sich vor, Sie haben ein foo.bar, Ein foo.baz Und ein baz Modul in Ihrem Paket. foo.bar Importiert foo.baz, Verwendet jedoch einen relativen Import.

    Wenn Sie nun foo.bar Nach bar verschieben, importiert Ihr Modul plötzlich ein anderes baz!

  2. Relative Importe sind nicht eindeutig. Selbst ohne sich im obigen Beispiel um das Modul bar zu bewegen, kann einem neuen Entwickler, der zu Ihrem Projekt kommt, vergeben werden, dass er nicht bemerkt hat, dass baz wirklich foo.baz Anstelle des Root- Moduls ist. Level baz Paket.

    Absolute Importe machen deutlich, welches Modul verwendet wird. Und wie import this Predigt, ist explizit besser als implizit.

  3. Python 3 hat implizite relative Importe insgesamt deaktiviert. Importe werden jetzt immer als absolut interpretiert, was bedeutet, dass im obigen Beispiel import baz immer das Modul der obersten Ebene importiert wird. Sie müssen stattdessen die explizite Importsyntax verwenden (from . import baz).

    Das Portieren des Beispiels von Python 2 bis 3 würde daher zu unerwarteten Problemen führen. Wenn Sie jetzt absolute Importe verwenden, ist Ihr Code zukunftssicher.

49
Martijn Pieters