ich habe eine Frage zu absoluten Importen in Python beantwortet , die ich aufgrund des Lesens des Python 2.5-Änderungsprotokolls und des zugehörigen PEP zu verstehen glaubte . Bei der Installation von Python 2.5 und dem Versuch, ein Beispiel für die ordnungsgemäße Verwendung zu erstellen, stelle from __future__ import absolute_importich jedoch fest, dass die Dinge nicht so klar sind.
Direkt aus dem oben verlinkten Änderungsprotokoll fasste diese Aussage mein Verständnis der absoluten Importänderung genau zusammen:
Angenommen, Sie haben ein Paketverzeichnis wie das folgende:
pkg/ pkg/__init__.py pkg/main.py pkg/string.pyDies definiert ein Paket
pkgmit dem Namenpkg.mainund denpkg.stringSubmodulen.Betrachten Sie den Code im main.py-Modul. Was passiert, wenn die Anweisung ausgeführt wird?
import string? In Python 2.4 und früheren Versionen wird zunächst im Verzeichnis des Pakets nach einem relativen Import gesucht, pkg / string.py gefunden, der Inhalt dieser Datei alspkg.stringModul importiert und das Modul an den Namen"string"impkg.mainNamespace des Moduls gebunden .
Also habe ich genau diese Verzeichnisstruktur erstellt:
$ ls -R
.:
pkg/
./pkg:
__init__.py main.py string.py
__init__.py und string.py sind leer. main.pyenthält den folgenden Code:
import string
print string.ascii_uppercase
Wie erwartet schlägt das Ausführen mit Python 2.5 mit einem fehl AttributeError :
$ python2.5 pkg/main.py
Traceback (most recent call last):
File "pkg/main.py", line 2, in <module>
print string.ascii_uppercase
AttributeError: 'module' object has no attribute 'ascii_uppercase'
Weiter unten im 2.5-Änderungsprotokoll finden wir jedoch Folgendes (Hervorhebung hinzugefügt):
In Python 2.5 können Sie das
importVerhalten mithilfe einerfrom __future__ import absolute_importDirektive auf absolute Importe umstellen . Dieses absolute Importverhalten wird in einer zukünftigen Version (wahrscheinlich Python 2.7) zum Standard. Sobald absolute Importe die Standardeinstellung sind,import stringwird immer die Version der Standardbibliothek gefunden.
Ich habe also erstellt pkg/main2.py, identisch mit, main.pyaber mit der zusätzlichen zukünftigen Importrichtlinie. Es sieht jetzt so aus:
from __future__ import absolute_import
import string
print string.ascii_uppercase
Das Ausführen mit Python 2.5 schlägt jedoch fehl mit AttributeError:
$ python2.5 pkg/main2.py
Traceback (most recent call last):
File "pkg/main2.py", line 3, in <module>
print string.ascii_uppercase
AttributeError: 'module' object has no attribute 'ascii_uppercase'
Dies steht im Widerspruch ziemlich flach die Aussage aus , import stringwird immer die std-lib - Version findet mit absoluten Importen aktiviert. Darüber hinaus habe ich trotz der Warnung, dass absolute Importe zum "neuen Standard" -Verhalten werden sollen, dasselbe Problem mit Python 2.7 mit oder ohne __future__Anweisung festgestellt:
$ python2.7 pkg/main.py
Traceback (most recent call last):
File "pkg/main.py", line 2, in <module>
print string.ascii_uppercase
AttributeError: 'module' object has no attribute 'ascii_uppercase'
$ python2.7 pkg/main2.py
Traceback (most recent call last):
File "pkg/main2.py", line 3, in <module>
print string.ascii_uppercase
AttributeError: 'module' object has no attribute 'ascii_uppercase'
sowie Python 3.5 mit oder ohne (vorausgesetzt, die printAnweisung wird in beiden Dateien geändert):
$ python3.5 pkg/main.py
Traceback (most recent call last):
File "pkg/main.py", line 2, in <module>
print(string.ascii_uppercase)
AttributeError: module 'string' has no attribute 'ascii_uppercase'
$ python3.5 pkg/main2.py
Traceback (most recent call last):
File "pkg/main2.py", line 3, in <module>
print(string.ascii_uppercase)
AttributeError: module 'string' has no attribute 'ascii_uppercase'
Ich habe andere Variationen davon getestet. Statt string.pyhabe ich ein leeres Modul erstellt - ein Verzeichnis mit dem Namen stringnur ein leeren enthalten __init__.py- und stattdessen die Einfuhr von Ausgabe aus main.py, ich habe cd‚dpkg und die Importe direkt aus dem REPL laufen. Weder diese Variationen (noch eine Kombination davon) haben die obigen Ergebnisse verändert. Ich kann dies nicht mit dem vereinbaren, was ich über die __future__Richtlinie und die absoluten Importe gelesen habe .
Es scheint mir, dass dies durch Folgendes leicht zu erklären ist (dies stammt aus den Python 2-Dokumenten, aber diese Aussage bleibt in denselben Dokumenten für Python 3 unverändert):
sys.path
(...)
Wie beim Programmstart initialisiert, ist das erste Element dieser Liste
path[0]das Verzeichnis, das das Skript enthält, mit dem der Python-Interpreter aufgerufen wurde. Wenn das Skriptverzeichnis nicht verfügbar ist (z. B. wenn der Interpreter interaktiv aufgerufen wird oder wenn das Skript aus der Standardeingabe gelesen wird),path[0]ist dies die leere Zeichenfolge, die Python anweist, zuerst die Module im aktuellen Verzeichnis zu suchen.
Also, was vermisse ich? Warum tut die __future__Aussage scheinbar nicht das, was sie sagt, und wie lässt sich dieser Widerspruch zwischen diesen beiden Abschnitten der Dokumentation sowie zwischen beschriebenem und tatsächlichem Verhalten lösen?