2008-10-11 9 views
70

Estoy un poco confundido por la multitud de formas en que puede importar módulos en Python.¿Cuáles son las buenas reglas generales para las importaciones de Python?

import X 
import X as Y 
from A import B 

he estado leyendo sobre el alcance y los espacios de nombres, pero me gustaría algunos consejos prácticos sobre cuál es la mejor estrategia, en qué circunstancias y por qué. ¿Deberían ocurrir las importaciones a nivel de módulo o a nivel de método/función? En el __init__.py o en el código del módulo en sí?

Mi pregunta no es realmente respondidas por "Python packages - import by class, not file" a pesar de que está obviamente relacionado.

+0

Ver http://stackoverflow.com/questions/187453/import-package-vs-import-packagespecifictype –

+0

Ver http://stackoverflow.com/questions/186472/from-x-import-a-versus-import -x-xa –

Respuesta

63

En el código de producción en nuestra empresa, tratamos de sigue las siguientes reglas

colocamos las importaciones al principio del archivo, justo después de cadena de documentación del archivo principal, por ejemplo:

""" 
Registry related functionality. 
""" 
import wx 
# ... 

Ahora bien, si se importa una clase que es uno de los pocos en el módulo importado, importamos la nombrar directamente, por lo que en el código sólo tenemos que utilizar la última parte, por ejemplo:

from RegistryController import RegistryController 
from ui.windows.lists import ListCtrl, DynamicListCtrl 

hay módulos, sin embargo, que contienen docenas de clases, por ejemplo, lista de todas las posibles excepciones Luego importamos el mismo módulo y referencia a ella en el código:

from main.core import Exceptions 
# ... 
raise Exceptions.FileNotFound() 

Utilizamos el import X as Y lo menos posible, ya que hace que la búsqueda de la utilización de un módulo o clase difícil en particular. A veces, sin embargo, usted tiene que utilizar si lo desea importar dos clases que tienen el mismo nombre, sino que existen en diferentes módulos, por ejemplo:

from Queue import Queue 
from main.core.MessageQueue import Queue as MessageQueue 

Como regla general, no hacemos las importaciones dentro de los métodos - simplemente hacen que el código sea más lento y menos legible. Algunos pueden encontrar que esta es una buena manera de resolver fácilmente el problema de las importaciones cíclicas, pero una mejor solución es la reorganización del código.

+4

"simplemente hacen que el código sea más lento" no es cierto. Ha sido probado aquí: http://stackoverflow.com/a/4789963/617185 – kmonsoor

12

que normalmente usa import X el nivel de módulo. Si solo necesita un solo objeto de un módulo, use from X import Y.

Sólo use import X as Y en caso de que usted se enfrenta otra manera con un nombre choque.

Yo sólo uso las importaciones en el nivel de función para importar cosas que necesito cuando se utiliza el módulo como el módulo principal, como:

def main(): 
    import sys 
    if len(sys.argv) > 1: 
    pass 

HTH

0

El import X as Y es útil si tiene diferentes implementaciones del mismo módulo/clase.

Con algunos anidados try..import..except ImportError..import s puede ocultar la aplicación desde el código. Ver lxml etree import example:

try: 
    from lxml import etree 
    print("running with lxml.etree") 
except ImportError: 
    try: 
    # Python 2.5 
    import xml.etree.cElementTree as etree 
    print("running with cElementTree on Python 2.5+") 
    except ImportError: 
    try: 
     # Python 2.5 
     import xml.etree.ElementTree as etree 
     print("running with ElementTree on Python 2.5+") 
    except ImportError: 
     try: 
     # normal cElementTree install 
     import cElementTree as etree 
     print("running with cElementTree") 
     except ImportError: 
     try: 
      # normal ElementTree install 
      import elementtree.ElementTree as etree 
      print("running with ElementTree") 
     except ImportError: 
      print("Failed to import ElementTree from any known place") 
2

por lo general tratan de utilizar la regularmente import modulename, a menos que el nombre del módulo es largo, o se utiliza a menudo ..

Por ejemplo, me gustaría hacer ..

from BeautifulSoup import BeautifulStoneSoup as BSS 

.so que puedo hacer soup = BSS(html) en lugar de BeautifulSoup.BeautifulStoneSoup(html)

O ..

from xmpp import XmppClientBase 

..instead de la importación de la totalidad de XMPP cuando yo sólo uso el XmppClientBase

El uso de import x as y es útil si desea importar nombres de método muy largos o para evitar una importación/variable/clase/método existente (por lo tanto, mething usted debe tratar de evitar por completo, pero no siempre es posible)

decir que quiero ejecutar una función main() de otro guión, pero ya tengo una función main() ..

from my_other_module import main as other_module_main 

..wouldn't reemplazar mi función main con my_other_module de main

Ah, una cosa - no hacer from x import * - que hace que su código muy difícil de entender, ya que no puede ver fácilmente en un método era (from x import *; from y import *; my_func() - donde ¿está definido my_func?)

En todos los casos, se pudo acaba de hacer import modulename y luego hacer modulename.subthing1.subthing2.method("test") ...

El material from x import y as z es para su comodidad - utilizarlo siempre que va a hacer que su código sea más fácil de leer o escribir!

+2

En mi humilde opinión, aquí hay algunas ideas erróneas ... 1) * "Importación de todo el xmpp cuando solo uso ..." *: esto falsamente implica que este enfoque es "más ligero", pero Python cargará e iniciará todo el módulo de todos modos, independientemente de cuántos objetos haya importado. En cuanto a la "contaminación del espacio de nombres", ambos agregarán una * entrada * única al espacio de nombres local: 'xmpp' o' XmppClientBase'. Por lo tanto, este razonamiento no es válido – MestreLion

+2

2) * "ya que no puede ver fácilmente de dónde vino un método" *: verdadero para * imports, pero * también * verdadero para su enfoque de usar 'as' solo para acortar un nombre de módulo/objeto . ¿De dónde viene 'BSS()'? Usar 'from' también sufre (un poco) de esto:' from mymod import MyClass'. Ahora, 300 líneas más adelante, ve 'clase MyOtherClass (MyClass):' ... ahora, ¿de dónde vino MyClass? Un lector está obligado a volver siempre al encabezado para ver dónde se importó el objeto desde – MestreLion

5

Otros han cubierto la mayor parte del terreno aquí, pero solo quería agregar un caso en el que usaré import X as Y (temporalmente), cuando estoy probando una nueva versión de una clase o módulo.

Entonces, si estábamos migrando a una nueva implementación de un módulo, pero no queríamos cortar la base de código sobre todo al mismo tiempo, podríamos escribir un módulo xyz_new y hacer esto en los archivos fuente que habíamos migrado :

import xyz_new as xyz 

Luego, una vez que cortamos lo largo de toda la base de código, le basta con sustituir el módulo xyz con xyz_new y cambiar todas las importaciones de vuelta a

import xyz 
+0

. Me lo ganaste. –

3

NO hacer esto:

from X import * 

a menos que esté absolutamente seguro de que usará todas y cada una de las cosas en ese módulo. E incluso entonces, probablemente debería reconsiderar el uso de un enfoque diferente.

Aparte de eso, es solo una cuestión de estilo.

from X import Y 

es bueno y le ahorra mucha escritura. Yo tiendo a usar que cuando estoy usando algo en él con bastante frecuencia, pero si va a importar mucho de ese módulo, usted podría terminar con una declaración de importación que se parece a esto:

from X import A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P 

Usted obtiene la idea.Es entonces cuando las importaciones como

import X 

resultan útiles. O eso o si realmente no estoy usando nada en X con mucha frecuencia.

+0

'de X import *' tiene sus usos, p. con pyparsing –

+0

Estoy de acuerdo. Pero, en general, no es un buen hábito entrar. Nada me molesta más que tener que rastrear qué función vino de qué módulo porque hay muchas declaraciones de x import * type. –

34

Permítanme pegar una parte de la conversación en la lista de correo django-dev iniciado por Guido van Rossum:

[...] Por ejemplo, es parte de las guías de estilo Google Python [1] que todas las importaciones deben importar un módulo, no una clase o función de ese módulo . Hay muchas más clases y funciones que los módulos , por lo que recordar de dónde viene una cosa en particular es mucho más fácil si se le agrega un nombre de módulo al . A menudo, los módulos múltiples definen cosas con el mismo nombre, por lo que un lector del código no tiene que volver al principio del archivo para ver desde qué módulo se importa un nombre de pila.

Fuente:http://groups.google.com/group/django-developers/browse_thread/thread/78975372cdfb7d1a

1: http://code.google.com/p/soc/wiki/PythonStyleGuide#Module_and_package_imports

+0

IMO esta debería ser la forma preferida de importación, especialmente en proyectos grandes. –

1

Cuando se tiene una biblioteca bien escrito, que a veces es el caso en Python, sólo debéis importarlo y utilizarlo como él. La biblioteca bien escrita tiende a quitar vida e idioma, resultando en un agradable código de lectura, donde raramente hace referencia a la biblioteca. Cuando una biblioteca está bien escrita, no debería necesitar cambiar el nombre ni demasiada frecuencia.

import gat 

node = gat.Node() 
child = node.children() 

A veces no es posible escribirlo de esta manera, o bien, si desea levantar cosas de la biblioteca que importó.

from gat import Node, SubNode 

node = Node() 
child = SubNode(node) 

A veces haces esto por muchas cosas, si la cadena de importación se desborda 80 columnas, Es buena idea hacer esto:

from gat import (
    Node, SubNode, TopNode, SuperNode, CoolNode, 
    PowerNode, UpNode 
) 

La mejor estrategia es mantener todas estas importaciones sobre la la parte superior del archivo. Preferiblemente ordenados alfabéticamente, import-statements primero, luego de import-statements.

Ahora te digo por qué esta es la mejor convención.

Python podría haber tenido una importación automática, que se vería desde las importaciones principales para el valor cuando no se puede encontrar desde el espacio de nombres global. Pero esta no es una buena idea. Explico brevemente por qué. Además de ser más complicado de implementar que de simple importación, los programadores no pensarían tanto en las dependencias y descubrirían que las cosas importadas deberían hacerse de otra manera que solo investigar las importaciones.

La necesidad de descubrir las dependencias es una de las razones por las cuales las personas odian "de ... importar *". Sin embargo, existen algunos ejemplos malos donde necesita hacer esto, por ejemplo, opengl -wrappings.

Por lo tanto, las definiciones de importación son realmente valiosas ya que definen las dependencias del programa. Es la forma en que deberías explotarlos. De ellos puede comprobar rápidamente de dónde se importa una función extraña.

0

estoy con Jason en el hecho de no utilizar

from X import * 

Pero en mi caso (no soy un experto programador, por lo que mi código no cumple con el estilo de codificación muy bien) que suele hacer en mis programas de un archivo con todas las constantes como la versión del programa, los autores, los mensajes de error y todas esas cosas, por lo que el archivo son sólo definiciones, a continuación, hago la importación

from const import * 

eso me ahorra mucho tiempo. Pero es el único archivo que tiene esa importación, y es porque todo dentro de ese archivo son solo declaraciones variables.

Hacer ese tipo de importación en un archivo con clases y definiciones puede ser útil, pero cuando tiene que leer ese código, pasa mucho tiempo buscando funciones y clases.

8

Alguien por encima de dicha que

from X import A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P 

es equivalente a

import X 

import X permite modificaciones directos a A-P, mientras que from X import ... crea copias de A-P. Para from X import A..P no recibirá actualizaciones de las variables si se modifican. Si los modifica, solo modificará su copia, pero X sí sabe sobre sus modificaciones.

Si A-P son funciones, no sabrá la diferencia.

+0

En particular, si quiere usar 'simulacro 'en pruebas unitarias para simular decir' X.A', entonces eso solo funciona si usó 'import X'. – RemcoGerlich

Cuestiones relacionadas