71 votes

Style de codage d'importation Python

J'ai découvert un nouveau modèle. Est ce motif bien connu ou qu'est-ce que l'opinion à ce sujet?

En gros, j'ai du mal à scrubbing en haut et en bas des fichiers source pour comprendre ce module, les importations sont disponibles et ainsi de suite, donc maintenant, au lieu de

import foo
from bar.baz import quux

def myFunction():
    foo.this.that(quux)

J'ai déplacer toutes mes importations dans la fonction où elles sont effectivement utilisées., comme ceci:

def myFunction():
    import foo
    from bar.baz import quux

    foo.this.that(quux)

Ce qui fait un peu les choses. Tout d'abord, j'ai rarement accidentellement polluer mes modules avec le contenu des autres modules. Je pourrais définir le __all__ variable pour le module, mais alors je dois mettre à jour le module évolue, et qui n'aide pas l'espace de noms de la pollution pour le code qui vit en fait dans le module.

Deuxièmement, j'ai rarement jusqu'à la fin avec une litanie des importations en haut de mes modules, la moitié ou plus de qui je n'ai plus besoin parce que j'ai refait il. Enfin, je trouve ce modèle plus facile à lire, puisque chaque nom de référence est là, dans le corps de la fonction.

125voto

aaronasterling Points 25749

Le haut-voté réponse à cette question est bien mis en forme, mais tout à fait tort sur la permformance. Laissez-moi vous montrer

Performance

Top Importation

import random

def f():
    L = []
    for i in xrange(1000):
        L.append(random.random())


for i in xrange(1000):
    f()

$ time python import.py

real        0m0.721s
user        0m0.412s
sys         0m0.020s

D'importation dans le Corps de la Fonction

def f():
    import random
    L = []
    for i in xrange(1000):
        L.append(random.random())

for i in xrange(1000):
    f()

$ time python import2.py

real        0m0.661s
user        0m0.404s
sys         0m0.008s

Comme vous pouvez le voir, il peut être plus efficace pour importer le module de la fonction. La raison pour cela est simple. Il se déplace de référence à partir de l'une des références mondiales pour un local de référence. Cela signifie que, pour Disponible au moins, le compilateur émet LOAD_FAST instructions au lieu de LOAD_GLOBAL instructions. Ce sont, comme le nom l'indique, plus rapide. Les autres répondeur gonflés artificiellement les performances de la recherche en sys.modules par l'importation de chaque itération de la boucle.

En règle générale, il est préférable d'importer au top mais la performance n'est pas la raison, si vous accédez au module de beaucoup de temps. Les raisons en sont que l'on peut garder une trace de ce qu'est un module dépend de plus en plus facilement et que cela est compatible avec la plupart du reste de l'Python univers.

57voto

Ryan Points 7423

Ce ne sont quelques inconvénients.

Les tests

A tout hasard, vous souhaitez tester votre module par le biais d'exécution de modification, il peut le rendre plus difficile. Au lieu de faire

import mymodule
mymodule.othermodule = module_stub

Vous aurez à faire

import othermodule
othermodule.foo = foo_stub

Cela signifie que vous allez avoir à patcher le othermodule à l'échelle mondiale, plutôt que de simplement changer ce à quoi la référence dans mymodule points.

Le Suivi Des Dépendances

Cela ne met pas en évidence ce que les modules de votre module dépend. C'est particulièrement irritant si vous utilisez beaucoup de bibliothèques tierces ou sont ré-organisation du code.

J'ai eu de maintenir un code existant utilisé importations inline tous sur la place, il fait le code extrêmement difficile à refactoriser ou de reconditionnement.

Remarques Sur Les Performances

En raison de la façon python caches modules, il n'y a pas de gain de performance. En fait, depuis le module est dans l'espace de noms local, il y a un léger gain de performance de l'importation de modules dans une fonction.

Top Importation

import random

def f():
    L = []
    for i in xrange(1000):
        L.append(random.random())

for i in xrange(10000):
    f()


$ time python test.py 

real   0m1.569s
user   0m1.560s
sys    0m0.010s

D'importation dans le Corps de la Fonction

def f():
    import random
    L = []
    for i in xrange(1000):
        L.append(random.random())

for i in xrange(10000):
    f()

$ time python test2.py

real    0m1.385s
user    0m1.380s
sys     0m0.000s

23voto

dF. Points 29787

Quelques problèmes avec cette approche:

  • Il n'est pas immédiatement évident lors de l'ouverture du fichier modules dont il dépend.
  • Il va confondre les programmes qui ont pour analyser les dépendances, telles que l' py2exe, py2app etc.
  • Que sur les modules que vous utilisez dans de nombreuses fonctions? Vous aurez jusqu'à la fin avec beaucoup de redondant importe ou vous allez avoir quelques en haut du fichier et de certains à l'intérieur des fonctions.

Alors... il est préférable de mettre toutes les importations en haut du fichier. J'ai trouvé que si mon importations être dur à suivre, cela signifie généralement que j'ai trop de code que je serais mieux de le diviser en deux ou plusieurs fichiers.

Certaines situations où j' ai trouvé les importations à l'intérieur de fonctions utiles:

  • Pour traiter les dépendances circulaires (si vous vraiment ne pouvez pas l'éviter)
  • Plate-forme de code spécifique

Aussi: mettre les importations à l'intérieur de chaque fonction est en fait pas sensiblement plus lent qu'en haut du fichier. Le premier temps de chaque module est chargé, il est mis en sys.modules, et tous les frais d'importation uniquement le temps de regarder en haut du module, ce qui est relativement rapide (il n'est pas rechargé).

10voto

Russell Bryant Points 623

Une autre chose utile à noter est que la syntaxe from module import * intérieur d'une fonction a été supprimée dans Python 3.0.

Vous en trouverez une brève mention sous "Syntaxe supprimée" ici:

http://docs.python.org/3.0/whatsnew/3.0.html

3voto

dbr Points 66401

Les gens ont très bien expliqué pourquoi, afin d'éviter les importations, mais pas vraiment d'alternative flux de travail pour aborder les raisons pour lesquelles vous voulez en premier lieu.

J'ai du mal à scrubbing en haut et en bas des fichiers source pour comprendre ce module, les importations sont disponibles et ainsi de suite

À vérifier pour les importations-je utiliser pylint. Il ne statique(ish)-analyse de code Python, et l'une des (nombreuses) choses, il vérifie est pas utilisé importations. Par exemple, le script suivant..

import urllib
import urllib2

urllib.urlopen("http://stackoverflow.com")

..générera le message suivant:

example.py:2 [W0611] Unused import urllib2

Comme pour la vérification de la disposition des importations, en général, je compter sur TextMate est (assez simpliste) de l'achèvement lorsque vous appuyez sur la touche Echap, il complète le mot en cours avec d'autres personnes dans le document. Si j'ai fait, import urllib, urll[Esc] sera étendue à d' urllib, sinon je saute au début du fichier et ajoutez le à l'importation.

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