web-dev-qa-db-fra.com

Utilisez 'import module' ou 'from module import'?

J'ai essayé de trouver un guide complet indiquant s'il est préférable d'utiliser import module ou from module import? Je viens juste de commencer avec Python et j'essaie de commencer avec les meilleures pratiques en tête.

En gros, j'espérais que quelqu'un pourrait partager ses expériences, quelles préférences d'autres développeurs ont et quel est le meilleur moyen d'éviter tout pièges sur la route?

351
Filip Dupanović

La différence entre import module et from module import foo est principalement subjective. Choisissez celui que vous préférez et soyez cohérent dans votre utilisation. Voici quelques points pour vous aider à décider.

import module

  • Avantages:
    • Moins de maintenance de vos déclarations import. Il n'est pas nécessaire d'ajouter d'autres importations pour commencer à utiliser un autre élément du module.
  • Inconvénients:
    • Taper module.foo dans votre code peut être fastidieux et redondant (l'ennui peut être minimisé en utilisant import module as mo puis en tapant mo.foo)

from module import foo

  • Avantages:
    • Moins de dactylographie à utiliser foo
    • Plus de contrôle sur les éléments d'un module accessibles
  • Inconvénients:
    • Pour utiliser un nouvel élément du module, vous devez mettre à jour votre instruction import.
    • Vous perdez le contexte à propos de foo. Par exemple, ce que ceil() fait par rapport à math.ceil() est moins clair.

Quelle que soit la méthode choisie, mais non utilise from module import *.

Pour tout grand ensemble de code raisonnable, si vous import *, vous le cimenterez probablement dans le module, sans possibilité de le supprimer. C’est parce qu’il est difficile de déterminer quels éléments utilisés dans le code proviennent de 'module', ce qui vous permet d’arriver facilement au point où vous pensez que vous n’utilisez plus import, mais il est extrêmement difficile de etre sur.

412
Mark Roddy

Il y a un autre détail ici, non mentionné, lié à l'écriture dans un module. Cela n’est peut-être pas très courant, mais j'en ai eu besoin de temps en temps.

En raison de la manière dont les références et la liaison de noms fonctionnent en Python, si vous souhaitez mettre à jour un symbole dans un module, disons foo.bar, depuis l'extérieur de ce module, et que le code d'importation "voir" qui change, vous devez importer foo a certaine manière. Par exemple:

module foo:

bar = "apples"

module a:

import foo
foo.bar = "oranges"   # update bar inside foo module object

module b:

import foo           
print foo.bar        # if executed after a's "foo.bar" assignment, will print "oranges"

Toutefois, si vous importez des noms de symboles au lieu de noms de modules, cela ne fonctionnera pas.

Par exemple, si je fais cela dans le module a:

from foo import bar
bar = "oranges"

Aucun code en dehors d'une barre ne verra "oranges" car mon réglage de barre affectait simplement le nom "bar" à l'intérieur du module a, il ne "pénétrait" pas dans "l'objet module foo et ne mettait pas à jour sa" barre ".

120

Même si beaucoup de gens ont déjà expliqué import vs import from, je voudrais essayer d'expliquer un peu plus ce qui se passe sous le capot et où se trouvent tous les changements.


import foo:

Importe foo et crée une référence à ce module dans l'espace de noms actuel. Ensuite, vous devez définir le chemin du module terminé pour accéder à un attribut ou à une méthode particulière à partir de l'intérieur du module.

Par exemple. foo.bar mais pas bar

from foo import bar:

Importe foo et crée des références à tous les membres répertoriés (bar). Ne définit pas la variable foo.

Par exemple. bar mais pas baz ni foo.baz

from foo import *:

Importe foo et crée des références à tous les objets publics définis par ce module dans l'espace de nom actuel (tout ce qui est répertorié dans __all__ si __all__ existe, sinon tout ce qui ne commence pas par _). Ne définit pas la variable foo.

Par exemple. bar et baz mais pas _qux ou foo._qux.


Voyons maintenant quand nous faisons import X.Y:

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

Vérifiez sys.modules avec le nom os et 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() et locals() l'espace de nom dicté avec os et 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'
>>>

Dans l'exemple ci-dessus, nous avons constaté que seul os est inséré dans les espaces de noms local et global. Donc, nous devrions pouvoir utiliser:

 >>> 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 l'espace de noms locals (), vous ne pourrez plus accéder à os ainsi qu'à os.path bien qu'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
>>>

Parlons maintenant de import from:

from:

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

Vérifiez sys.modules avec os et 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'>

Nous avons trouvé que dans sys.modules nous avions retrouvé la même chose que nous avions précédemment en utilisant import name

OK, vérifions à quoi ça ressemble dans locals() et globals() noms d'espace de nom:

>>> 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 le nom path 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 'chemin' 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 un alias:

>>> 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 pas de chemin défini:

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

Les deux moyens sont pris en charge pour une raison: il y a des moments où l’une est plus appropriée que l’autre.

  • import module: Bien quand vous utilisez beaucoup de bits du module. L'inconvénient est que vous devez qualifier chaque référence avec le nom du module.

  • from module import ...: Les éléments importés sont utilisables directement sans préfixe de nom de module. L'inconvénient est que vous devez répertorier chaque chose que vous utilisez et que le code ne précise pas d'où provient quelque chose.

Ce qui à utiliser dépend de ce qui rend le code clair et lisible, et a beaucoup à faire avec les préférences personnelles. Je me penche généralement vers import module parce que, dans le code, il est très clair d'où vient un objet ou une fonction. J'utilise from module import ... lorsque j'utilise un objet/une fonction a lot dans le code.

38
dwc

Personnellement, j'utilise toujours

from package.subpackage.subsubpackage import module

puis accéder à tout comme

module.function
module.modulevar

etc. La raison en est qu’en même temps, vous avez une courte invocation et vous définissez clairement l’espace de nom de module de chaque routine, ce qui est très utile si vous devez rechercher l’utilisation d’un module donné dans votre source.

Inutile de dire que n'utilisez pas l'import *, car il pollue votre espace de noms et il ne vous dit pas d'où vient une fonction donnée (de quel module)

Bien sûr, vous pouvez avoir des problèmes si vous avez le même nom de module pour deux modules différents dans deux packages différents, comme

from package1.subpackage import module
from package2.subpackage import module

dans ce cas, bien sûr, vous rencontrez des problèmes, mais il y a alors une forte indication que votre présentation de paquet est défectueuse, et vous devez la repenser.

33
Stefano Borini
import module

Il est préférable d’utiliser de nombreuses fonctions du module.

from module import function

Il est préférable d’éviter de polluer l’espace de noms global avec toutes les fonctions et tous les types d’un module lorsque vous n’avez besoin que de function.

14
Andrew Hare

Voici une autre différence non mentionnée. Ceci est copié textuellement de http://docs.python.org/2/tutorial/modules.html

Notez que lorsque vous utilisez

from package import item

l'élément peut être soit un sous-module (ou un sous-package) du package, soit un autre nom défini dans le package, tel qu'une fonction, une classe ou une variable. L'instruction d'importation teste d'abord si l'élément est défini dans le package; sinon, il suppose qu'il s'agit d'un module et tente de le charger. S'il ne parvient pas à le trouver, une exception ImportError est générée.

Au contraire, lorsque vous utilisez une syntaxe telle que

import item.subitem.subsubitem

chaque article sauf le dernier doit être un colis; Le dernier élément peut être un module ou un package, mais ne peut pas être une classe, une fonction ou une variable définie dans l’élément précédent.

8
user2141737

Je viens de découvrir une différence plus subtile entre ces deux méthodes.

Si le module foo utilise une importation suivante:

from itertools import count

Ensuite, le module bar peut utiliser par erreur count comme s'il était défini dans foo et non dans itertools:

import foo
foo.count()

Si foo utilise:

import itertools

l'erreur est toujours possible, mais moins probable. bar doit:

import foo
foo.itertools.count()

Cela m'a causé des ennuis. J'ai eu un module qui par erreur a importé une exception d'un module qui ne l'a pas défini, l'a seulement importé d'un autre module (en utilisant from module import SomeException). Lorsque l'importation n'était plus nécessaire et supprimée, le module incriminé était cassé.

8
Jan Wrobel
import package
import module

Avec import, le jeton doit être un module (un fichier contenant les commandes Python) ou un package (un dossier du sys.path contenant un fichier __init__.py.).

Quand il y a des sous-paquets:

import package1.package2.package
import package1.package2.module

la configuration requise pour le dossier (package) ou le fichier (module) est identique, mais le dossier ou le fichier doit se trouver dans package2 qui doit figurer dans package1, et package1 et package2 doit contenir les fichiers __init__.py. https://docs.python.org/2/tutorial/modules.html

Avec le style d'importation from:

from package1.package2 import package
from package1.package2 import module

le package ou le module entre l'espace de noms du fichier contenant l'instruction import sous la forme module (ou package) au lieu de package1.package2.module. Vous pouvez toujours vous connecter à un nom plus pratique:

a = big_package_name.subpackage.even_longer_subpackage_name.function

Seul le style d'importation from vous permet de nommer une fonction ou une variable particulière:

from package3.module import some_function

est autorisé, mais

import package3.module.some_function 

n'est pas autorisé.

5
Bennett Brown

Puisque je suis aussi un débutant, je vais essayer d’expliquer cela d’une manière simple: En Python, nous avons trois types d’instructions import qui sont:

1. Importations génériques:

import math

ce type d'importation est mon préféré, le seul inconvénient de cette technique d'importation est que si vous avez besoin d'utiliser une fonction du module, vous devez utiliser la syntaxe suivante:

math.sqrt(4)

bien sûr, cela augmente l'effort de dactylographie, mais en tant que débutant, cela vous aidera à garder une trace du module et de la fonction qui lui est associée (un bon éditeur de texte réduira considérablement l'effort de dactylographie et est recommandé) .

L'effort de frappe peut être encore réduit en utilisant cette instruction d'importation:

import math as m

maintenant, au lieu d'utiliser math.sqrt(), vous pouvez utiliser m.sqrt().

2. Importations de fonctions:

from math import sqrt

, ce type d'importation convient mieux si votre code n'a besoin d'accéder qu'à une ou plusieurs fonctions du module, mais que pour utiliser tout nouvel élément du module, vous devez mettre à jour la déclaration d'importation.

3. Importations universelles:

from math import * 

Bien qu'il réduise considérablement les efforts de frappe, il n'est toutefois pas recommandé, car votre code sera rempli de différentes fonctions du module et leur nom pourrait entrer en conflit avec le nom des fonctions définies par l'utilisateur. exemple:

Si vous avez une fonction de votre propre sqrt nommé et que vous importez des maths, votre fonction est sécurisée: il y a votre sqrt et il y a math.sqrt. Cependant, si vous importez des mathématiques *, vous avez un problème: deux fonctions différentes portant exactement le même nom. Source: Codecademy

5
Shashank Rawat

Pour ajouter à ce que les gens ont dit à propos de from x import *: outre qu’il est plus difficile de dire d’où viennent les noms, cela jette des correcteurs de code comme Pylint. Ils rapporteront ces noms en tant que variables non définies.

4
DNS

Ma propre réponse à cette question dépend principalement du premier, du nombre de modules que je vais utiliser. Si je n’en utilise qu’un ou deux, je vais souvent utiliser from ... import dans la mesure où le nombre de frappes au clavier est réduit dans le reste du fichier, mais si je vais utiliser plusieurs modules, je préfère simplement import car cela signifie que chaque référence de module est auto-documentée. Je peux voir d'où vient chaque symbole sans avoir à chercher.

Habituellement, je préfère le style d'auto-documentation de l'importation brut et ne change qu'en importation lorsque le nombre de fois que je dois taper le nom du module dépasse 10 à 20, même s'il n'y a qu'un seul module importé.

L'une des différences significatives que j'ai découvertes et dont étonnamment personne n'a parlé est l'utilisation d'une importation simple vous pouvez accéder à private variable et private functions à partir du module importé, ce qui n'est pas possible avec from-import déclaration.

enter image description here

Code en image:

setting.py

public_variable = 42
_private_variable = 141
def public_function():
    print("I'm a public function! yay!")
def _private_function():
    print("Ain't nobody accessing me from another module...usually")

plain_importer.py

import settings
print (settings._private_variable)
print (settings.public_variable)
settings.public_function()
settings._private_function()

# Prints:
# 141
# 42
# I'm a public function! yay!
# Ain't nobody accessing me from another module...usually

from_importer.py

from settings import *
#print (_private_variable) #doesn't work
print (public_variable)
public_function()
#_private_function()   #doesn't work
1
Saurav Sahu

Je voudrais ajouter à cela, il y a quelque chose à considérer lors des appels d'importation:

J'ai la structure suivante:

mod/
    __init__.py
    main.py
    a.py
    b.py
    c.py
    d.py

main.py:

import mod.a
import mod.b as b
from mod import c
import d

dis.dis montre la différence:

  1           0 LOAD_CONST               0 (-1)
              3 LOAD_CONST               1 (None)
              6 IMPORT_NAME              0 (mod.a)
              9 STORE_NAME               1 (mod)

  2          12 LOAD_CONST               0 (-1)
             15 LOAD_CONST               1 (None)
             18 IMPORT_NAME              2 (b)
             21 STORE_NAME               2 (b)

  3          24 LOAD_CONST               0 (-1)
             27 LOAD_CONST               2 (('c',))
             30 IMPORT_NAME              1 (mod)
             33 IMPORT_FROM              3 (c)
             36 STORE_NAME               3 (c)
             39 POP_TOP

  4          40 LOAD_CONST               0 (-1)
             43 LOAD_CONST               1 (None)
             46 IMPORT_NAME              4 (mod.d)
             49 LOAD_ATTR                5 (d)
             52 STORE_NAME               5 (d)
             55 LOAD_CONST               1 (None)

En fin de compte, ils ont le même aspect (STORE_NAME est le résultat dans chaque exemple), mais il convient de le noter si vous devez prendre en compte les quatre importations circulaires suivantes:

exemple 1

foo/
   __init__.py
   a.py
   b.py
a.py:
import foo.b 
b.py:
import foo.a
>>> import foo.a
>>>

Cela marche

exemple2

bar/
   __init__.py
   a.py
   b.py
a.py:
import bar.b as b
b.py:
import bar.a as a
>>> import bar.a
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "bar\a.py", line 1, in <module>
    import bar.b as b
  File "bar\b.py", line 1, in <module>
    import bar.a as a
AttributeError: 'module' object has no attribute 'a'

Pas de dé

exemple3

baz/
   __init__.py
   a.py
   b.py
a.py:
from baz import b
b.py:
from baz import a
>>> import baz.a
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "baz\a.py", line 1, in <module>
    from baz import b
  File "baz\b.py", line 1, in <module>
    from baz import a
ImportError: cannot import name a

Problème similaire ... mais clairement de x import y n’est pas identique à import import x.y à y

exemple4

qux/
   __init__.py
   a.py
   b.py
a.py:
import b 
b.py:
import a
>>> import qux.a
>>>

Celui-ci fonctionne aussi

0
ahfx

Module d'importation - Vous n'avez pas besoin d'efforts supplémentaires pour extraire une autre chose du module. Il présente des inconvénients tels que le typage redondant

Importation de module depuis - Moins de saisie et plus de contrôle sur les éléments d’un module auxquels vous pouvez accéder. Pour utiliser un nouvel élément du module, vous devez mettre à jour votre déclaration d’importation.

0
Dlucidone