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_import
ich 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.py
Dies definiert ein Paket
pkg
mit dem Namenpkg.main
und denpkg.string
Submodulen.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.string
Modul importiert und das Modul an den Namen"string"
impkg.main
Namespace 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.py
enthä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
import
Verhalten mithilfe einerfrom __future__ import absolute_import
Direktive 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 string
wird immer die Version der Standardbibliothek gefunden.
Ich habe also erstellt pkg/main2.py
, identisch mit, main.py
aber 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 string
wird 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 print
Anweisung 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.py
habe ich ein leeres Modul erstellt - ein Verzeichnis mit dem Namen string
nur 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?