Qu’est-ce que from __future__ import absolute_import fait réellement ?

| | | | | | | | |

J'ai répondu à une question concernant les importations absolues en Python, que je pensais comprendre en lisant le journal des modifications Python 2.5 et PEP. Cependant, lors de l'installation de Python 2.5 et de la tentative de création d'un exemple d'utilisation correcte de depuis __future__ import absolute_import, je me rends compte que les choses ne sont pas si claires.

Droit du journal des modifications lié ci-dessus, ceci déclaration résume avec précision ma compréhension du changement d'importation absolu :

Disons que vous avez un répertoire de packages comme celui-ci :

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

Cela définit un package nommé pkg contenant le pkg.main et pkg.string sous-modules.

Considérez le code dans le module main.py. Que se passe-t-il s'il exécute l'instruction import string ? Dans Python 2.4 et versions antérieures, il va d'abord chercher dans le répertoire du package pour effectuer une importation relative, trouve pkg/string.py, importe le contenu de ce fichier en tant que module pkg.string, et ce module est lié au nom "string" dans les noms des modules pkg.main rythme.

J'ai donc créé cette structure de répertoire exacte :

$ ls -R .: pkg/ ./pkg: __init__.py main.py string .py 

__init__.py et string.py sont vides. main.py contient le code suivant :

import string print string.ascii_uppercase 

Comme prévu, l'exécution avec Python 2.5 échoue avec une AttributeError :

$ python2.5 pkg/main.py Traceback (dernier appel le plus récent) : Fichier "pkg/main.py", ligne 2 , dans <module> print string.ascii_uppercase AttributeError : l'objet "module" n'a pas d'attribut "ascii_uppercase" 

Cependant, plus loin dans le journal des modifications 2.5, nous trouvons ceci (nous soulignons) :

Dans Python 2.5, vous pouvez basculer le comportement de import vers des importations absolues à l'aide d'une directive from __future__ import absolute_import. Ce comportement d'importation absolue deviendra la valeur par défaut dans une future version (probablement Python 2.7). Une fois que les importations absolues sont la valeur par défaut, import string trouvera toujours la version de la bibliothèque standard.

J'ai donc créé pkg/main2.py, identique à main.py mais avec la future directive d'importation supplémentaire. Il ressemble maintenant à ceci :

from __future__ import absolute_import import string print string.ascii_uppercase 

L'exécution avec Python 2.5, cependant... échoue avec un AttributeError :

$ python2.5 pkg/main2.py Traceback (appel le plus récent en dernier) : fichier "pkg/main2.py", ligne 3, dans < ;module> print string.ascii_uppercase AttributeError : l'objet "module" n'a pas d'attribut "ascii_uppercase" 

Cela contredit assez catégoriquement l'affirmation selon laquelle importer la chaîne sera toujours recherchez la version std-lib avec les importations absolues activées. De plus, malgré l'avertissement que les importations absolues sont programmées pour devenir le "nouveau comportement par défaut", j'ai rencontré ce même problème en utilisant Python 2.7, avec ou sans la directive __future__ :

$ python2.7 pkg/main.py Traceback (dernier appel le plus récent) : Fichier "pkg/main.py", ligne 2, dans <module> print string.ascii_uppercase AttributeError : objet "module" n'a pas d'attribut "ascii_uppercase" $ python2.7 pkg/main2.py Traceback (appel le plus récent en dernier) : fichier "pkg/main2.py", ligne 3, dans <module> print string.ascii_uppercase AttributeError : objet "module" n'a pas d'attribut "ascii_uppercase" 

ainsi que Python 3.5, avec ou sans (en supposant que l'instruction print est modifiée dans les deux fichiers) :

$ python3.5 pkg/main.py Traceback (dernier appel le plus récent) : Fichier "pkg/main.py", ligne 2, dans <module> print(string.ascii_uppercase) AttributeError : module "string " n'a pas d'attribut "ascii_uppercase" $ python3.5 pkg/main2.py Trac eback (appel le plus récent en dernier) : fichier "pkg/main2.py", ligne 3, dans <module> print(string.ascii_uppercase) AttributeError : le module "string" n'a pas d'attribut "ascii_uppercase" 

J'ai testé d'autres variantes de ceci. Au lieu de string.py, j'ai créé un module vide -- un répertoire nommé string contenant seulement un __init__.py vide -- et à la place d'émettre des importations depuis main.py, j'ai cd"d vers pkg et j'exécute les importations directement depuis le REPL. Aucune de ces variantes (ni une combinaison d'entre eux) a changé les résultats ci-dessus. Je ne peux pas concilier cela avec ce que j'ai lu sur la directive __future__ et les importations absolues.

Il me semble que cela est facilement explicable par ce qui suit (ceci provient de la documentation Python 2 mais ceci l'instruction reste inchangée dans la même documentation pour Python 3) :

sys.path

(...)

Comme initialisé au démarrage du programme, le premier élément de cette liste, path[0], est le répertoire contenant le script qui a été utilisé pour invoquer l'interpréteur Python. Si le directeur du script y n'est pas disponible (par exemple, si l'interpréteur est appelé de manière interactive ou si le script est lu à partir de l'entrée standard), path[0] est la chaîne vide, qui dirige Python pour rechercher des modules dans le répertoire courant en premier.

Alors qu'est-ce que je rate ? Pourquoi l'instruction __future__ ne fait apparemment pas ce qu'elle dit, et quelle est la résolution de cette contradiction entre ces deux sections de la documentation, ainsi qu'entre le comportement décrit et le comportement réel ?

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