Tenho respondido uma pergunta sobre as importações absolutos em Python, que eu pensei que eu entendi com base na leitura do changelog Python 2.5 e acompanhando PEP . No entanto, ao instalar o Python 2.5 e tentar criar um exemplo de uso adequado from __future__ import absolute_import, percebo que as coisas não são tão claras.
Diretamente do changelog acima, esta declaração resumiu com precisão minha compreensão da mudança absoluta de importação:
Digamos que você tenha um diretório de pacotes como este:
pkg/ pkg/__init__.py pkg/main.py pkg/string.pyIsso define um pacote chamado
pkgcontendo os subpkg.main-pkg.stringmódulos e .Considere o código no módulo main.py. O que acontece se a instrução for executada
import string? No Python 2.4 e versões anteriores, ele procurará primeiro no diretório do pacote uma importação relativa, localiza pkg / string.py, importa o conteúdo desse arquivo comopkg.stringmódulo e esse módulo é vinculado ao nome"string"nopkg.mainespaço de nome do módulo.
Então, eu criei essa estrutura de diretório exata:
$ ls -R
.:
pkg/
./pkg:
__init__.py main.py string.py
__init__.pye string.pyestão vazios. main.pycontém o seguinte código:
import string
print string.ascii_uppercase
Como esperado, executar isso com o Python 2.5 falha com um 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'
No entanto, mais adiante no changelog 2.5, encontramos o seguinte (ênfase adicionada):
No Python 2.5, você pode mudar
importo comportamento para importações absolutas usando umafrom __future__ import absolute_importdiretiva. Esse comportamento de importação absoluta se tornará o padrão em uma versão futura (provavelmente Python 2.7). Uma vez que as importações absolutas são o padrão,import stringsempre encontrará a versão da biblioteca padrão.
Criei assim pkg/main2.py, idêntico a, main.pymas com a futura diretiva de importação adicional. Agora, fica assim:
from __future__ import absolute_import
import string
print string.ascii_uppercase
Executar isso com o Python 2.5, no entanto ... falha com um 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'
Este bastante categoricamente contradiz a afirmação de que import stringirá sempre encontrar a versão std-lib com as importações absolutos habilitado. Além do mais, apesar do aviso de que importações absolutas estão agendadas para se tornar o comportamento "novo padrão", encontrei o mesmo problema usando o Python 2.7, com ou sem a __future__diretiva:
$ 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'
bem como Python 3.5, com ou sem (assumindo que a printinstrução foi alterada nos dois arquivos):
$ 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'
Eu testei outras variações disso. Em vez de string.py, eu criei um módulo vazio - um diretório chamado stringcontendo apenas um vazio __init__.py- e em vez de emitir as importações a partir main.py, eu tenho cd'd para pkge executar as importações diretamente do REPL. Nenhuma dessas variações (nem uma combinação delas) alterou os resultados acima. Não consigo conciliar isso com o que li sobre a __future__diretiva e as importações absolutas.
Parece-me que isso é facilmente explicável pelo seguinte (isso é dos documentos do Python 2, mas essa declaração permanece inalterada nos mesmos documentos do Python 3):
sys.path
(...)
Conforme inicializado na inicialização do programa, o primeiro item desta lista
path[0], é o diretório que contém o script usado para chamar o interpretador Python. Se o diretório do script não estiver disponível (por exemplo, se o intérprete for chamado interativamente ou se o script for lido a partir da entrada padrão),path[0]será a string vazia, que instrui o Python a pesquisar os módulos no diretório atual primeiro.
Então o que estou perdendo? Por que a __future__declaração aparentemente não faz o que diz e qual é a resolução dessa contradição entre essas duas seções da documentação, bem como entre o comportamento descrito e o real?