que o __future__ import absolute_import realmente faz?

| | | | | | | | |

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 o pkg.main e pkg.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ódulo pkg.string, e esse módulo está vinculado ao nome "string" nos nomes do módulo pkg.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 diretiva from __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?

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

News


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