Relative vs. absolute Imports

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Malachite
User
Beiträge: 34
Registriert: Sonntag 24. Juni 2012, 13:43
Wohnort: Berlin

Moin,

gemäß PEP8 sind relative Imports ja zu vermeiden. Allerdings habe ich heute hier folgendes gelesen:
The only acceptable syntax for relative imports is from .[module] import name. All import forms not starting with . are interpreted as absolute imports. (PEP 0328)
Nach meinem Verständnis heißt das, dass ein

Code: Alles auswählen

from package import module
nicht im eigenen Verzeichnis nachschaut,

Code: Alles auswählen

from .package import module
hingegen nur dort.

So wie es aussieht, ist genau das der Fall, wie folgender Test zeigt:

Verzeichnisstruktur:

Code: Alles auswählen

/tmp/pytest/
    |- __init__.py
    |- xml.py
    |- loremipsum.py
__init__.py:

Code: Alles auswählen

__all__ = ['tkinter']

import tkinter
print(tkinter)

import loremipsum
print(loremipsum)
xml.py und loremipsum.py:

Code: Alles auswählen

print("I'm imported!\n")
Output:

Code: Alles auswählen

>>> import pytest
<module 'tkinter' from '/usr/lib/python3.2/tkinter/__init__.py'>

Traceback (most recent call last):
  File "<input>", line 1, in <module>
  File "pytest/__init__.py", line 6, in <module>
    import loremipsum
ImportError: No module named loremipsum
Mit anderen Worten, für eigene Module und Pakete muss ich relative Imports benutzen. Wieso steht in PEP8 immer noch das hier?
Relative imports for intra-package imports are highly discouraged. Always use the absolute package path for all imports. Even now that PEP 328 is fully implemented in Python 2.5, its style of explicit relative imports is actively discouraged; absolute imports are more portable and usually more readable.
Hat jemand einfach nur vergessen, PEP8 zu aktualisieren oder gibt es noch einen anderen Weg, eigene Module zu importieren (außer mit importlib.import_module())?
Zuletzt geändert von Malachite am Dienstag 14. August 2012, 16:58, insgesamt 2-mal geändert.
BlackJack

@Malachite: Wieso *musst* Du relative Importe benutzen‽ PEP8 rät davon ab. Verwende absolute und gut ist's.
Malachite
User
Beiträge: 34
Registriert: Sonntag 24. Juni 2012, 13:43
Wohnort: Berlin

BlackJack hat geschrieben:Verwende absolute und gut ist's.
Eben nicht.

Code: Alles auswählen

>>> import pytest
[…]
Traceback (most recent call last):
  File "<input>", line 1, in <module>
  File "pytest/__init__.py", line 6, in <module>
    import loremipsum
ImportError: No module named loremipsum
>>> import os
>>> os.listdir('pytest')
['__pycache__', '__init__.py', 'tkinter.py', 'loremipsum.py']
↑ This, siehe meinen ersten Post. Wenn ich in pytest/__init__.py einen relativen Import hinschreibe, funktioniert er ohne Probleme. Absolute Imports funktionieren bei mir nicht bei lokalen Modulen (nennt man die lokal?). Und wegen dieses Textes in den Release Notes…

P.S.: PyDev kennzeichnet absolute Imports übrigens auch als "Unresolved Import", wenn es kein entsprechendes globales Modul gibt.
Zuletzt geändert von Malachite am Freitag 10. August 2012, 23:12, insgesamt 1-mal geändert.
BlackJack

@Malachite: Wenn absolute importe nicht funktionieren scheinst Du eine sehr exotische Python-Implementierung zu haben. Oder das Paket ist nicht korrekt installiert/im Pfad.
Malachite
User
Beiträge: 34
Registriert: Sonntag 24. Juni 2012, 13:43
Wohnort: Berlin

BlackJack hat geschrieben:Wenn absolute importe nicht funktionieren scheinst Du eine sehr exotische Python-Implementierung zu haben
Nö, das normale Paket, das in den Ubuntu-Paketquellen liegt, also CPython afaik; Version 3.2. Außerdem meldet PyDev wie gesagt ja auch Fehler. Wenn ich die Analyse allerdings auf Python 2.7 umstelle, nicht mehr.
Und absolute Importe funktionieren ja, aber nur global.
BlackJack hat geschrieben:Oder das Paket ist nicht korrekt installiert/im Pfad.
Meinst du den Interpreter oder das Python-Paket? PyDev fügt ein Paket normalerweise automatisch zu sys.path hinzu.
BlackJack

@Malachite: Was meinst Du mit absolute Importe funktionieren nur „global”? Kann es sein dass Du die Fehlannahme triffst, dass ``import loremipsum`` ein absoluter Import ist‽ Das wäre einer wenn es ein `loremipsum`-Modul oder -Paket im Modul-Suchpfad gäbe. Und bei Python 2.x ist das ein implizit relativer weil dort halt auch immer relativ zum importierenden Modul geschaut wird — was bei 3.x jetzt abgeschafft wurde, weil es verwirrend werden kann. Absolut bedeutet — wie bei Dateisystempfaden auch — *alles ab der Wurzel* anzugeben. Dein `loremipsum` ist nicht auf oberster Ebene sondern steckt im Paket `pytest` — das muss man also mit angeben damit man wirklich und ganz sicher einen absoluten Import hat: ``from pytest import loremipsum``.
Malachite
User
Beiträge: 34
Registriert: Sonntag 24. Juni 2012, 13:43
Wohnort: Berlin

BlackJack hat geschrieben: Und bei Python 2.x ist das ein implizit relativer weil dort halt auch immer relativ zum importierenden Modul geschaut wird — was bei 3.x jetzt abgeschafft wurde, weil es verwirrend werden kann.
Und genau das schafft neue Verwirrungen, weil PEP8 nicht entsprechend angepasst wurde. Das war der Punkt, der mein Programm am Funktionieren gehindert hat. Sobald ich relative Imports für programminterne und absolute für anderen Module benutze, funktioniert es ja.
Dein `loremipsum` ist nicht auf oberster Ebene sondern steckt im Paket `pytest`
Weiß ich, deswegen wird es ja auch von pytest/__init__.py importiert.
lunar

@Malachite: Wieso sollte PEP 8 angepasst werden? Der von Dir zitierte Abschnitt ist korrekt, absolute Imports funktionieren auch für paketinterne Module. Wenn das bei Dir nicht der Fall ist, dann ist das Paket wahrscheinlich nicht installiert, oder Du befindest Dich im falschen Arbeitsverzeichnis.
BlackJack

@Malachite: Wenn Du weisst das a) `loremipsum` in einem Paket steckt und b) PEP 8 absolute Importe dringend empfiehlt und Python 3 absolute Importe zwingend erfordert, warum wunderst Du Dich dann das es in `pytest.__init__.py` Probleme gibt wenn Du dort *keinen absoluten Import* verwendest beziehungsweise einen mit einem Modul dass es bei Dir gar nicht gibt‽ Es gibt kein `loremipsum`-Modul. Es gibt nur ein `pytest.loremipsum`-Modul. *Dass* musst Du *absolut* importieren.

Ich kann mich da lunar nur anschliessen: PEP 8 sagt *importiere absolut*. Was soll an der Aussage denn nun bitte angepasst werden? Das war vor Python 3 eine sinnvolle Empfehlung und ist mit Python 3 zu einer notwendigen Empfehlung geworden.
Malachite
User
Beiträge: 34
Registriert: Sonntag 24. Juni 2012, 13:43
Wohnort: Berlin

The only acceptable syntax for relative imports is from .[module] import name. All import forms not starting with . are interpreted as absolute imports. (PEP 0328)
*headbang* Wieso kapiere ich jetzt erst, wie das gemeint ist?

Vielen Dank für eure Geduld :oops:
Antworten