Ho risposto a una domanda relativa alle importazioni assolute in Python, che pensavo di aver capito basandomi sulla lettura del log delle modifiche di Python 2.5 e sull'accompagnamento di PEP . Tuttavia, dopo aver installato Python 2.5 e aver tentato di creare un esempio di utilizzo corretto from __future__ import absolute_import, mi rendo conto che le cose non sono così chiare.
Direttamente dal log delle modifiche sopra citato, questa affermazione ha riassunto accuratamente la mia comprensione del cambiamento di importazione assoluto:
Supponiamo che tu abbia una directory dei pacchetti come questa:
pkg/ pkg/__init__.py pkg/main.py pkg/string.pyQuesto definisce un pacchetto chiamato
pkgcontenente ipkg.mainepkg.stringsottomoduli.Considera il codice nel modulo main.py. Cosa succede se esegue l'istruzione
import string? In Python 2.4 e precedenti, cercherà prima nella directory del pacchetto di eseguire un'importazione relativa, trova pkg / string.py, importa il contenuto di quel file comepkg.stringmodulo e quel modulo è associato al nome"string"nellopkg.mainspazio dei nomi del modulo.
Quindi ho creato questa esatta struttura di directory:
$ ls -R
.:
pkg/
./pkg:
__init__.py main.py string.py
__init__.pye string.pysono vuoti. main.pycontiene il seguente codice:
import string
print string.ascii_uppercase
Come previsto, l'esecuzione di questo con Python 2.5 non riesce con un 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'
Tuttavia, più avanti nel log delle modifiche 2.5, troviamo questo (enfasi aggiunta):
In Python 2.5, puoi cambiare
importil comportamento in importazioni assolute usando unafrom __future__ import absolute_importdirettiva. Questo comportamento di importazione assoluta diventerà il valore predefinito in una versione futura (probabilmente Python 2.7). Una volta che le importazioni assolute sono predefinite,import stringtroverà sempre la versione della libreria standard.
Ho così creato pkg/main2.py, identico main.pyma con la futura direttiva sulle importazioni aggiuntiva. Ora sembra così:
from __future__ import absolute_import
import string
print string.ascii_uppercase
L'esecuzione con Python 2.5, tuttavia ... non riesce con un 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'
Ciò contraddice in modo piuttosto netto l'affermazione che import stringtroverà sempre la versione std-lib con le importazioni assolute abilitate. Inoltre, nonostante l'avvertimento che le importazioni assolute sono programmate per diventare il comportamento "nuovo predefinito", ho riscontrato questo stesso problema utilizzando sia Python 2.7, con o senza la __future__direttiva:
$ 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'
così come Python 3.5, con o senza (supponendo che l' printistruzione sia cambiata in entrambi i file):
$ 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'
Ho testato altre varianti di questo. Invece di string.py, ho creato un modulo vuoto - una directory di nome stringche contiene solo un vuoto __init__.py- e, invece di emettere importazioni da main.py, ho cd'd per pkged eseguire le importazioni direttamente dal REPL. Nessuna di queste variazioni (né una combinazione di esse) ha modificato i risultati sopra. Non posso conciliare questo con ciò che ho letto sulla __future__direttiva e sulle importazioni assolute.
Mi sembra che ciò sia facilmente spiegabile come segue (questo proviene dai documenti di Python 2 ma questa affermazione rimane invariata negli stessi documenti di Python 3):
sys.path
(...)
Come inizializzato all'avvio del programma, il primo elemento di questo elenco
path[0], è la directory contenente lo script utilizzato per richiamare l'interprete Python. Se la directory di script non è disponibile (ad es. Se l'interprete viene richiamato in modo interattivo o se lo script viene letto dall'input standard),path[0]è la stringa vuota che indirizza Python a cercare prima i moduli nella directory corrente.
Quindi cosa mi sto perdendo? Perché la __future__dichiarazione sembra non fare ciò che dice, e qual è la soluzione di questa contraddizione tra queste due sezioni della documentazione, nonché tra il comportamento descritto e quello reale?