364 votes

`from ... import` vs `import .`

Je me demande s'il y a une différence entre le fragment de code

from urllib import request

et le fragment

import urllib.request

ou si elles sont interchangeables. Si elles sont interchangeables, quelle est la syntaxe "standard"/"préférée" (s'il y en a une) ?

1 votes

Je ne suis pas un expert en matière d'importation, donc je ne laisserai pas de réponse, mais il y a une différence dans la façon dont les choses entrent dans le système. sys.modules : jetez un coup d'œil à ceci réponse (à la fin). (Peut-être y a-t-il quelqu'un qui peut l'expliquer mieux que moi)

317voto

g.d.d.c Points 20164

Cela dépend de la façon dont vous voulez accéder à l'importation lorsque vous y faites référence.

from urllib import request
# access request directly.
mine = request()

import urllib.request
# used as urllib.request
mine = urllib.request()

Vous pouvez également aliaser les choses vous-même lorsque vous importez pour plus de simplicité ou pour éviter de masquer les inserts intégrés :

from os import open as open_
# lets you use os.open without destroying the 
# built in open() which returns file handles.

4 votes

Je viens d'essayer d'importer urllib.request et cela ne fonctionne pas du tout (python 2.6.5 Ubuntu).

9 votes

Vous devez utiliser un trait de soulignement à la fin (plutôt qu'en tête) pour éviter tout conflit avec les modules intégrés.

0 votes

@deadly - mauvaise habitude - cela empêche un avertissement de l'IDE dans Eclipse d'utiliser parfois un trait de soulignement en tête. Merci.

245voto

sjcipher Points 2626

De nombreuses personnes ont déjà expliqué import vs from Je vais donc essayer d'expliquer un peu plus ce qui se passe sous le capot, là où se trouve la véritable différence.

Tout d'abord, laissez-moi vous expliquer exactement ce que font les déclarations d'importation de base.

import X

Importe le module X et crée une référence à ce module dans le espace de nom actuel. Vous devez ensuite définir un chemin d'accès complet au module pour accéder à un attribut ou à une méthode particulière depuis l'intérieur du module (par ex : X.name o X.attribute )

from X import *

Importe le module X et crée des références à tous les objets publics définis par ce module dans l'espace de noms actuel (c'est-à-dire tout ce qui qui n'a pas un nom commençant par _ ) ou tout autre nom que vous avez mentionné.

Ou, en d'autres termes, après avoir exécuté cette déclaration, vous pouvez simplement utiliser un nom simple (non qualifié) pour faire référence aux choses définies dans le module X . Mais X lui-même n'est pas défini, donc X.name ne fonctionne pas. Et si name était déjà défini, il est remplacé par la nouvelle version. Et si le nom dans X est changé pour pointer vers un autre objet, votre module ne le remarquera pas.

Cela rend tous les noms du module disponibles dans l'espace de nom local.

Maintenant, voyons ce qui se passe quand on fait import X.Y :

>>> import sys
>>> import os.path

Vérifiez sys.modules avec le nom os y os.path :

>>> sys.modules['os']
<module 'os' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/os.pyc'>
>>> sys.modules['os.path']
<module 'posixpath' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.pyc'>

Vérifiez globals() y locals() espace de nom dict avec nom os y os.path :

 >>> globals()['os']
<module 'os' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/os.pyc'>
>>> locals()['os']
<module 'os' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/os.pyc'>
>>> globals()['os.path']
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: 'os.path'
>>>    

A partir de l'exemple ci-dessus, nous avons constaté que seulement os est ajouté aux espaces de noms local et global. Ainsi, nous devrions être en mesure d'utiliser os :

 >>> os
 <module 'os' from     
  '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/os.pyc'>
 >>> os.path
 <module 'posixpath' from      
 '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.pyc'>
 >>>

mais pas path :

>>> path
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'path' is not defined 
>>>

Une fois que vous avez supprimé le os de locals() vous ne pourrez pas accéder à l'un ou l'autre des espaces de noms suivants os o os.path même s'ils existent dans sys.modules :

>>> del locals()['os']
>>> os
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'os' is not defined
>>> os.path
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'os' is not defined
>>>

Voyons maintenant from .

from

>>> import sys
>>> from os import path

Vérifiez sys.modules avec le nom os y os.path :

>>> sys.modules['os']
<module 'os' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/os.pyc'>
>>> sys.modules['os.path']
<module 'posixpath' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.pyc'>

Alors sys.modules ressemble à ce qu'il était lorsque nous avons importé en utilisant import name .

Ok. Vérifions ce qu'est le locals() y globals() Les dicts d'espace de noms ressemblent :

>>> globals()['path']
<module 'posixpath' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.pyc'>
>>> locals()['path']
<module 'posixpath' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.pyc'>
>>> globals()['os']
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: 'os'
>>>

Vous pouvez y accéder en utilisant path mais pas par os.path :

>>> path
<module 'posixpath' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.pyc'>
>>> os.path
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'os' is not defined
>>>

Supprimons 'path' de locals() :

>>> del locals()['path']
>>> path
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'path' is not defined
>>>

Un dernier exemple utilisant l'aliasing :

>>> from os import path as HELL_BOY
>>> locals()['HELL_BOY']
<module 'posixpath' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.pyc'>
>>> globals()['HELL_BOY']
<module 'posixpath' from /System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.pyc'>
>>>

Et aucun chemin défini :

>>> globals()['path']
Traceback (most recent call last):
 File "<stdin>", line 1, in <module>
KeyError: 'path'
>>>

Un des pièges de l'utilisation de from

Lorsque vous importez le même name à partir de deux modules différents :

>>> import sys
>>> from os import stat
>>> locals()['stat']
<built-in function stat>
>>>
>>> stat
<built-in function stat>

Importer les statistiques de shutil encore :

>>>
>>> from shutil import stat
>>> locals()['stat']
<module 'stat' from 
'/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/stat.pyc'>
>>> stat
<module 'stat' from 
'/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/stat.pyc'>
>>>

LE DERNIER IMPORTATEUR GAGNERA

8 votes

En effet, mais pour moi, c'est un peu déroutant avec tous ces espaces de noms et ainsi de suite. Je préfère donc utiliser simplement import x et ensuite x.what_is_necessary. À mon humble avis, je pense que c'est plus lisible et plus facile d'éviter la confusion, et de cette façon, vous évitez les conflits de noms, l'ambiguïté et toutes ces sortes de choses...non ?

20 votes

J'aime cette réponse car elle enseigne comment attraper des poissons au lieu de fournir des poissons.

4 votes

Que signifie "from . import <classyouwant>" ? Je ne sais pas à quoi le point fait référence.

30voto

Karl Barker Points 3045

Il y a très peu de différence dans la fonctionnalité, mais la première forme est préférée, car vous pouvez faire

from urllib import request, parse, error

alors que dans la deuxième forme, cela devrait être

import urllib.request, urllib.parse, urllib.error

et vous devriez faire référence en utilisant le nom entièrement qualifié, ce qui est beaucoup moins élégant.

29voto

Anas Elghafari Points 394

Il y a une différence. Dans certains cas, l'un des deux fonctionnera et l'autre pas. Voici un exemple : disons que nous avons la structure suivante :

foo.py
mylib\
    a.py
    b.py

Maintenant, je veux importer b.py sur a.py . Et je veux importer a.py a foo . Comment dois-je m'y prendre ? Deux déclarations, dans a J'écris :

import b

Sur foo.py J'écris :

import mylib.a

Eh bien, cela va générer un ImportError en essayant d'exécuter foo.py . L'interpréteur se plaindra de l'instruction import dans a.py ( import b ) en disant qu'il n'y a pas de module b. Alors comment résoudre ce problème ? Dans une telle situation, il suffit de modifier l'instruction d'importation dans le fichier a a import mylib.b ne fonctionnera pas puisque a y b sont tous deux dans mylib . La solution ici (ou du moins une solution) est d'utiliser l'importation absolue :

from mylib import b

Source : Python : importation d'un module qui importe un module

4voto

Senthil Kumaran Points 14934

Vous utilisez Python3 étaient urllib dans le paquet. Les deux formes sont acceptables et aucune forme d'importation n'est préférée à l'autre. Parfois, lorsqu'il y a plusieurs répertoires de paquets impliqués, vous pouvez utiliser la première forme from x.y.z.a import s

Dans ce cas particulier avec le paquet urllib, la deuxième manière import urllib.request et l'utilisation de urllib.request est la façon dont la bibliothèque standard l'utilise uniformément.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X