Eu respondi a uma pergunta sobre importações absolutas em Python, que achei ter entendido com base na leitura o log de alterações do Python 2.5 e o PEP. No entanto, ao instalar o Python 2.5 e tentar criar um exemplo de uso adequado de de __future__ import absolute_import
, percebo que as coisas não estão tão claras.
Direto do changelog vinculado acima, isso declaração resumiu com precisão minha compreensão da mudança de importação absoluta:
Digamos que você tenha um diretório de pacotes como este:
pkg/pkg/__init__.py pkg/main.py pkg/string.py
Isso define um pacote chamado
pkg
contendo opkg.main
epkg.string
submódulos.Considere o código no módulo main.py. O que acontece se ele executar a instrução
import string
? No Python 2.4 e anteriores, ele irá primeiro procurar no diretório do pacote para realizar uma importação relativa, encontra pkg/string.py, importa o conteúdo desse arquivo como o módulopkg.string
, e esse módulo está vinculado ao nome"string"
nos nomes do módulopkg.main
pace.
Então eu criei esta estrutura de diretórios exata:
$ ls -R .: pkg/ ./pkg: __init__.py main.py string .py
__init__.py
e string.py
estão vazios. main.py
contém o seguinte código:
import string print string.ascii_uppercase
Como esperado, executando isso com Python 2.5 falha com um AttributeError
:
$ python2.5 pkg/main.py Traceback (última chamada mais recente): Arquivo "pkg/main.py", linha 2 , em <módulo> print string.ascii_uppercase AttributeError: o objeto "module" não tem o atributo "ascii_uppercase"
Entretanto, mais adiante no changelog 2.5, encontramos isso (ênfase adicionada):
No Python 2.5, você pode alternar o comportamento de
import
" para importações absolutas usando uma diretivafrom __future__ import absolute_import
. Esse comportamento de importação absoluta se tornará o padrão em uma versão futura (provavelmente Python 2.7). Uma vez que importações absolutas são o padrão,import string
sempre encontrará a versão da biblioteca padrão.
Criei assim pkg/main2.py
, idêntico a main.py
mas com a diretiva de importação futura adicional. Agora fica assim:
from __future__ import absolute_import import string print string.ascii_uppercase
Executar isso com Python 2.5, no entanto... falha com um AttributeError
:
$ python2.5 pkg/main2.py Traceback (última chamada mais recente): Arquivo "pkg/main2.py", linha 3, em < ;módulo> print string.ascii_uppercase AttributeError: objeto "module" não tem atributo "ascii_uppercase"
Isso contradiz a afirmação de que importar string
sempre strong> encontre a versão std-lib com importações absolutas habilitadas. Além do mais, apesar do aviso de que as importações absolutas estão programadas para se tornar o comportamento "novo padrão", encontrei esse mesmo problema usando o Python 2.7, com ou sem a diretiva __future__
:
$ python2.7 pkg/main.py Traceback (última chamada mais recente): Arquivo "pkg/main.py", linha 2, em <module> print string.ascii_uppercase AttributeError: "module" object não tem atributo "ascii_uppercase" $ python2.7 pkg/main2.py Traceback (última chamada mais recente): Arquivo "pkg/main2.py", linha 3, em <module> print string.ascii_uppercase AttributeError: "module" object não tem o atributo "ascii_uppercase"
assim como Python 3.5, com ou sem (supondo que a instrução print
seja alterada em ambos os arquivos):
$ python3.5 pkg/main.py Traceback (última chamada mais recente): Arquivo "pkg/main.py", linha 2, em <module> print(string.ascii_uppercase) AttributeError: module "string " não tem atributo "ascii_uppercase" $ python3.5 pkg/main2.py Trac eback (última chamada mais recente): Arquivo "pkg/main2.py", linha 3, em <module> print(string.ascii_uppercase) AttributeError: o módulo "string" não tem o atributo "ascii_uppercase"
Eu testei outras variações disso. Em vez de string.py
, criei um módulo vazio -- um diretório chamado string
contendo apenas um __init__.py
vazio -- e em vez disso de emitir importações de main.py
, eu tenho cd
"d para pkg
e executo importações diretamente do REPL. Nenhuma dessas variações (nem uma combinação deles) alterou os resultados acima. Não consigo conciliar isso com o que li sobre a diretiva __future__
e importações absolutas.
Parece-me que isso é facilmente explicável por o seguinte (este é dos documentos do Python 2, mas este permanece inalterada nos mesmos documentos para Python 3):
sys.path
(...)
Como inicializado na inicialização do programa, o primeiro item desta lista,
path[0]
, é o diretório que contém o script que foi usado para invocar o interpretador Python. y não está disponível (por exemplo, se o interpretador for invocado interativamente ou se o script for lido da entrada padrão),path[0]
é a string vazia, que direciona o Python para pesquisar módulos no diretório atual primeiro.
Então, o que estou perdendo? Por que a instrução __future__
aparentemente não faz o que diz, e qual é a resolução dessa contradição entre essas duas seções de documentação, bem como entre o comportamento descrito e o real?