python - script - ¿Usar ''importar módulo'' o ''desde módulo importar''?
llamar funcion de otro archivo python (13)
A pesar de que muchas personas ya han explicado acerca de la import
contra la import from
, quiero tratar de explicar un poco más sobre lo que sucede debajo del capó y dónde están todos los lugares en los que cambia.
import foo
:
Importa foo
y crea una referencia a ese módulo en el espacio de nombres actual. Luego, debe definir la ruta del módulo completado para acceder a un atributo o método particular desde dentro del módulo.
Ej. foo.bar
pero no bar
from foo import bar
:
Importa foo
y crea referencias a todos los miembros enumerados ( bar
). No establece la variable foo
.
Por ejemplo, bar
pero no baz
o foo.baz
from foo import *
:
Importa foo
y crea referencias a todos los objetos públicos definidos por ese módulo en el espacio de nombres actual (todo lo que aparece en __all__
si __all__
existe, de lo contrario, todo lo que no comience con _
). No establece la variable foo
.
Por ejemplo, bar
y baz
pero no _qux
o foo._qux
.
Ahora veamos cuando import XY
:
>>> import sys
>>> import os.path
Compruebe sys.modules
con el nombre 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''>
Verifique los puntos de espacio de nombres globals()
y locals()
con 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''
>>>
Del ejemplo anterior, encontramos que solo el sistema os
se inserta en el espacio de nombres local y global. Entonces, deberíamos poder usar:
>>> 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''>
>>>
Pero no el path
.
>>> path
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name ''path'' is not defined
>>>
Una vez que elimine el sistema os
del espacio de nombres locals (), no podrá acceder tanto a os
como a os.path
aunque existan en 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
>>>
Ahora hablemos de import from
:
from
:
>>> import sys
>>> from os import path
Compruebe sys.modules
con 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''>
Encontramos que en sys.modules
encontramos lo mismo que hicimos anteriormente usando el import name
Bien, vamos a ver cómo se ve en locals()
dects del espacio de nombres locals()
y globals()
:
>>> 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''
>>>
Puede acceder usando la path
nombre no por 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
>>>
Vamos a eliminar ''ruta'' de los locals()
:
>>> del locals()[''path'']
>>> path
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name ''path'' is not defined
>>>
Un último ejemplo usando 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''>
>>>
Y ningún camino definido:
>>> globals()[''path'']
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: ''path''
>>>
¿He tratado de encontrar una guía completa sobre si es mejor usar el import module
o from module import
? Acabo de comenzar con Python y estoy tratando de comenzar con las mejores prácticas en mente.
Básicamente, esperaba que alguien pudiera compartir sus experiencias, qué preferencias tienen otros desarrolladores y cuál es la mejor manera de evitar cualquier problema en el futuro .
Acabo de descubrir una diferencia más sutil entre estos dos métodos.
Si el módulo foo
utiliza una importación siguiente:
from itertools import count
Luego, la bar
módulos puede, por error, count
como si estuviera definida en foo
, no en itertools
:
import foo
foo.count()
Si foo
usa:
import itertools
El error todavía es posible, pero es menos probable que se cometa. bar
necesita:
import foo
foo.itertools.count()
Esto me causó algunos problemas. Tuve un módulo que por error importó una excepción de un módulo que no lo definió, solo lo from module import SomeException
de otro módulo (usando from module import SomeException
). Cuando la importación ya no era necesaria y se eliminó, el módulo infractor se rompió.
Ambas formas son compatibles por una razón: hay veces en que una es más apropiada que la otra.
import module
: agradable cuando se utilizan muchos bits del módulo. El inconveniente es que deberá calificar cada referencia con el nombre del módulo.from module import ...
: agradable que los elementos importados se pueden usar directamente sin el prefijo de nombre de módulo. El inconveniente es que debe enumerar cada cosa que usa, y que no está claro en el código de dónde provino.
Lo que se debe usar depende de lo que hace que el código sea claro y legible, y tiene más que poco que ver con las preferencias personales. Me inclino hacia el import module
general porque en el código es muy claro de dónde proviene un objeto o función. Uso from module import ...
cuando uso mucho un objeto / función en el código.
Aquí hay otra diferencia no mencionada. Esto se copia textualmente de http://docs.python.org/2/tutorial/modules.html
Tenga en cuenta que al usar
from package import item
el elemento puede ser un submódulo (o subpaquete) del paquete, o algún otro nombre definido en el paquete, como una función, clase o variable. La declaración de importación primero prueba si el artículo está definido en el paquete; Si no, asume que es un módulo e intenta cargarlo. Si no puede encontrarlo, se genera una excepción ImportError.
Por el contrario, cuando se utiliza sintaxis como
import item.subitem.subsubitem
cada artículo excepto el último debe ser un paquete; el último elemento puede ser un módulo o un paquete, pero no puede ser una clase o función o variable definida en el elemento anterior.
Hay otro detalle aquí, no mencionado, relacionado con escribir en un módulo. Es posible que esto no sea muy común, pero lo he necesitado de vez en cuando.
Debido a la forma en que funcionan las referencias y el enlace de nombres en Python, si desea actualizar algún símbolo en un módulo, por ejemplo, foo.bar, desde fuera de ese módulo, y tiene otro código de importación "ver" que cambia, debe importar foo a de cierta manera. Por ejemplo:
módulo foo:
bar = "apples"
módulo a:
import foo
foo.bar = "oranges" # update bar inside foo module object
módulo b:
import foo
print foo.bar # if executed after a''s "foo.bar" assignment, will print "oranges"
Sin embargo, si importa nombres de símbolos en lugar de nombres de módulos, esto no funcionará.
Por ejemplo, si hago esto en el módulo a:
from foo import bar
bar = "oranges"
Ningún código fuera de una barra verá "naranjas" porque mi configuración de barra simplemente afectó al nombre "barra" dentro del módulo a, no "alcanzó" el objeto del módulo foo y actualizó su "barra".
Importar módulo: no es necesario realizar ningún esfuerzo adicional para obtener otra cosa del módulo. Tiene desventajas como la tipificación redundante.
Módulo Importar desde: menos escritura y más control sobre los elementos de un módulo al que se puede acceder. Para usar un nuevo elemento del módulo, debe actualizar su declaración de importación.
La diferencia entre el import module
y el from module import foo
es principalmente subjetiva. Elija el que más le guste y sea consistente en su uso. Aquí hay algunos puntos para ayudarte a decidir.
import module
- Pros:
- Menos mantenimiento de sus declaraciones de
import
. No es necesario agregar ninguna importación adicional para comenzar a usar otro elemento del módulo
- Menos mantenimiento de sus declaraciones de
- Contras:
- Escribir
module.foo
en su código puede ser tedioso y redundante (se puede minimizar el tedio usando elimport module as mo
luego escribiendomo.foo
)
- Escribir
from module import foo
- Pros:
- Menos mecanografía para usar
foo
- Más control sobre qué elementos de un módulo se puede acceder
- Menos mecanografía para usar
- Contras:
- Para usar un nuevo elemento del módulo, debe actualizar su declaración de
import
- Pierdes contexto sobre
foo
. Por ejemplo, está menos claro qué hacemath.ceil()
comparación conmath.ceil()
- Para usar un nuevo elemento del módulo, debe actualizar su declaración de
Cualquiera de los métodos es aceptable, pero no use from module import *
.
Para cualquier conjunto grande de código razonable, si import *
probablemente lo cimentará en el módulo, no podrá ser eliminado. Esto se debe a que es difícil determinar qué elementos utilizados en el código provienen del "módulo", lo que facilita llegar al punto en el que cree que ya no usa la import
pero es extremadamente difícil estar seguro.
Mi respuesta a esto depende principalmente de la primera, cuántos módulos diferentes usaré. Si solo voy a usar uno o dos, a menudo lo haré from
... import
ya que hace menos pulsaciones en el resto del archivo, pero si voy a utilizar muchos módulos diferentes, prefiero import
solo porque eso significa que cada referencia de módulo es autodocumentada. Puedo ver de dónde viene cada símbolo sin tener que cazar.
Usuully, prefiero el estilo de auto-documentación de importación simple y solo cambiar a "importar" cuando la cantidad de veces que tengo que escribir el nombre del módulo crece por encima de 10 a 20, incluso si solo se está importando un módulo.
Para agregar a lo que la gente ha dicho acerca from x import *
: además de hacer que sea más difícil saber de dónde provienen los nombres, esto arroja los comprobadores de códigos como Pylint. Ellos reportarán esos nombres como variables indefinidas.
Ya que también soy un principiante, intentaré explicar esto de una manera simple: en Python, tenemos tres tipos de declaraciones de import
que son:
1. Importaciones genéricas:
import math
este tipo de importación es mi favorito personal, el único inconveniente de esta técnica de importación es que si necesita usar cualquier función de módulo, debe usar la siguiente sintaxis:
math.sqrt(4)
por supuesto, aumenta el esfuerzo de escritura, pero como principiante, le ayudará a realizar un seguimiento del módulo y la función asociada a él (un buen editor de texto reducirá significativamente el esfuerzo de escritura y se recomienda).
El esfuerzo de escritura se puede reducir aún más utilizando esta declaración de importación:
import math as m
ahora, en lugar de usar math.sqrt()
puede usar m.sqrt()
.
2. Importaciones de funciones:
from math import sqrt
este tipo de importación es más adecuado si su código solo necesita acceder a una sola o pocas funciones del módulo, pero para usar cualquier elemento nuevo del módulo debe actualizar la declaración de importación.
3. Importaciones universales:
from math import
Aunque reduce considerablemente el esfuerzo de escritura, pero no se recomienda porque llenará su código con varias funciones del módulo y su nombre podría entrar en conflicto con el nombre de las funciones definidas por el usuario. ejemplo:
Si tiene una función de su propio sqrt denominado e importa matemática, su función es segura: existe su sqrt y existe math.sqrt. Sin embargo, si lo hace desde Math Import *, tiene un problema: dos funciones diferentes con el mismo nombre. Fuente: Codecademy
Yo personalmente uso siempre
from package.subpackage.subsubpackage import module
y luego acceder a todo como
module.function
module.modulevar
La razón es que al mismo tiempo tiene una invocación corta y define claramente el espacio de nombres de cada rutina en el módulo, algo que es muy útil si tiene que buscar el uso de un módulo determinado en su fuente.
No hace falta decir que no use la importación *, ya que contamina su espacio de nombres y no le dice de dónde proviene una función determinada (de qué módulo)
Por supuesto, puede tener problemas si tiene el mismo nombre de módulo para dos módulos diferentes en dos paquetes diferentes, como
from package1.subpackage import module
from package2.subpackage import module
En este caso, por supuesto que se encuentra con problemas, pero luego hay un fuerte indicio de que el diseño de su paquete es defectuoso y debe repensarlo.
import module
Es mejor cuando usas muchas funciones del módulo.
from module import function
Es mejor cuando desea evitar contaminar el espacio de nombres global con todas las funciones y tipos de un módulo cuando solo necesita la function
.
import package
import module
Con la import
, el token debe ser un módulo (un archivo que contenga comandos de Python) o un paquete (una carpeta en el sys.path
contenga un archivo __init__.py
.)
Cuando hay subpaquetes:
import package1.package2.package
import package1.package2.module
los requisitos para la carpeta (paquete) o el archivo (módulo) son los mismos, pero la carpeta o el archivo deben estar dentro del package2
que debe estar dentro del package1
, y tanto el package1
como el package1
deben contener archivos __init__.py
. https://docs.python.org/2/tutorial/modules.html
Con el estilo de importación:
from package1.package2 import package
from package1.package2 import module
el paquete o módulo ingresa al espacio de nombres del archivo que contiene la declaración de import
como module
(o package
) en lugar de package1.package2.module
. Siempre se puede enlazar a un nombre más conveniente:
a = big_package_name.subpackage.even_longer_subpackage_name.function
Solo el estilo de importación desde le permite nombrar una función o variable en particular:
from package3.module import some_function
esta permitido, pero
import package3.module.some_function
No se permite.