Was macht eigentlich from __future__ import absolute_import?

| | | | | | | | |

Ich habe eine Frage zu absoluten Importen in Python beantwortet, die ich aufgrund des Lesens von das Python 2.5-Änderungsprotokoll und die begleitenden PEP. Nach der Installation von Python 2.5 und dem Versuch, ein Beispiel für die korrekte Verwendung von from __future__ import absolute_import zu erstellen, stelle ich jedoch fest, dass die Dinge nicht so klar sind.

Direkt aus dem oben verlinkten Änderungsprotokoll, dies -Anweisung hat mein Verständnis der absoluten Importänderung genau zusammengefasst:

Nehmen wir an, Sie haben ein Paketverzeichnis wie dieses:

pkg/pkg/__init__.py pkg/main.py pkg/string.py 

Dies definiert ein Paket namens pkg, das pkg.main und enthält pkg.string-Submodule.

Betrachten Sie den Code im main.py-Modul. Was passiert, wenn es die Anweisung import string ausführt? In Python 2.4 und früher ist es wird zuerst im Verzeichnis des Pakets nachsehen, um einen relativen Import durchzuführen, findet pkg/string.py, importiert den Inhalt dieser Datei als pkg.string-Modul, und dieses Modul wird an den Namen gebunden "string" in den Namen des Moduls pkg.main Tempo.

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 wird dies mit Python 2.5 ausgeführt schlägt mit einem AttributeError fehl:

$ python2.5 pkg/main.py Traceback (letzter Aufruf zuletzt): Datei "pkg/main.py", Zeile 2 , in <Modul> print string.ascii_uppercase AttributeError: "module" object has no attribute "ascii_uppercase" 

Allerdings finden wir weiter unten im Änderungsprotokoll von 2.5 Folgendes (Hervorhebung hinzugefügt):

In Python 2.5 können Sie das Verhalten von import mithilfe der Direktive from __future__ import absolute_import auf absolute Importe umstellen. Dieses absolute Importverhalten wird zum Standard in eine zukünftige Version (wahrscheinlich Python 2.7). Sobald absolute Importe der Standard sind, findet import string immer die Version der Standardbibliothek.

Ich habe also pkg/main2.py erstellt, identisch mit main.py, aber mit der zusätzlichen zukünftigen import-Direktive. Es sieht jetzt so aus:

from __future__ import absolute_import import string print string.ascii_uppercase 

Die Ausführung mit Python 2.5 jedoch ... schlägt mit einem fehl AttributeError:

$ python2.5 pkg/main2.py Traceback (letzter Aufruf zuletzt): Datei "pkg/main2.py", Zeile 3, in < ;modul> print string.ascii_uppercase AttributeError: "module" object has no attribute "ascii_uppercase" 

Das widerspricht ziemlich rundweg der Aussage, dass import string immer finden Sie die std-lib-Version mit aktivierten absoluten Importen. Außerdem bin ich trotz der Warnung, dass absolute Importe zum „neuen Standard“-Verhalten werden sollen, auf dasselbe Problem gestoßen, wenn ich Python 2.7 mit oder ohne die Direktive __future__ verwende:

$ python2.7 pkg/main.py Traceback (letzter Aufruf zuletzt): Datei „pkg/main.py“, Zeile 2, in <module> print string.ascii_uppercase AttributeError: „module“ object hat kein Attribut "ascii_uppercase" $ python2.7 pkg/main2.py Traceback (letzter Aufruf zuletzt): Datei "pkg/main2.py", Zeile 3, in <module> print string.ascii_uppercase AttributeError: "module" object hat kein Attribut "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 (letzter Aufruf zuletzt): Datei „pkg/main.py“, Zeile 2, in <module> print(string.ascii_uppercase) AttributeError: module „string " hat kein Attribut "ascii_uppercase" $ python3.5 pkg/main2.py Trac eback (letzter Aufruf zuletzt): Datei "pkg/main2.py", Zeile 3, in <module> print(string.ascii_uppercase) AttributeError: module "string" has no attribute "ascii_uppercase" 

Ich habe andere Variationen davon getestet. Anstelle von string.py habe ich ein leeres Modul erstellt – ein Verzeichnis namens string, das nur eine leere __init__.py enthält – und stattdessen Importe aus main.py herauszugeben, habe ich cd"d zu pkg und führe Importe direkt aus der REPL aus. Keine dieser Varianten (noch eine Kombination davon) hat die obigen Ergebnisse verändert. Ich kann dies nicht mit dem in Einklang bringen, was ich über die __future__-Direktive und absolute Importe gelesen habe.

Mir scheint, dass dies leicht erklärbar ist von dem Folgenden (dies ist aus der Python 2-Dokumentation, aber this Anweisung bleibt in denselben Dokumenten für Python 3 unverändert):

sys.path

(...)

Wie beim Programmstart initialisiert, Das erste Element dieser Liste, path[0], ist das Verzeichnis, das das Skript enthält, das zum Aufrufen des Python-Interpreters verwendet wurde y nicht verfügbar ist (z. B. wenn der Interpreter interaktiv aufgerufen wird oder wenn das Skript von der Standardeingabe gelesen wird), ist path[0] der leere String, der Python anweist, Module in zu suchen aktuelles Verzeichnis zuerst.

Was übersehe ich also? Warum tut die __future__-Anweisung anscheinend nicht das, was sie sagt, und wie wird dieser Widerspruch zwischen diesen beiden Abschnitten der Dokumentation sowie zwischen beschriebenem und tatsächlichem Verhalten gelöst?

Shop

Learn programming in R: courses

$

Best Python online courses for 2022

$

Best laptop for Fortnite

$

Best laptop for Excel

$

Best laptop for Solidworks

$

Best laptop for Roblox

$

Best computer for crypto mining

$

Best laptop for Sims 4

$

Latest questions

NUMPYNUMPY

psycopg2: insert multiple rows with one query

12 answers

NUMPYNUMPY

How to convert Nonetype to int or string?

12 answers

NUMPYNUMPY

How to specify multiple return types using type-hints

12 answers

NUMPYNUMPY

Javascript Error: IPython is not defined in JupyterLab

12 answers


Wiki

Python OpenCV | cv2.putText () method

numpy.arctan2 () in Python

Python | os.path.realpath () method

Python OpenCV | cv2.circle () method

Python OpenCV cv2.cvtColor () method

Python - Move item to the end of the list

time.perf_counter () function in Python

Check if one list is a subset of another in Python

Python os.path.join () method