practicar - más de 400 ejercicios de programación en python pdf
Python: volver a cargar el componente Y importado con ''desde X importar Y''? (8)
Responder
De mis pruebas. La respuesta marcada, que sugiere una reload(X)
simple reload(X)
, no funciona.
De lo que puedo decir la respuesta correcta es:
import X
reload( X )
from X import Y
Prueba
Mi prueba fue la siguiente (Python 2.6.5 + bpython 0.9.5.2)
X.py:
def Y():
print "Test 1"
bpython
>>> from X import Y
>>> print Y()
Test 1
>>> # Edit X.py to say "Test 2"
>>> print Y()
Test 1
>>> reload( X ) # doesn''t work because X not imported yet
Traceback (most recent call last):
File "<input>", line 1, in <module>
NameError: name ''X'' is not defined
>>> import X
>>> print Y()
Test 1
>>> print X.Y()
Test 1
>>> reload( X ) # No effect on previous "from" statements
>>> print Y()
Test 1
>>> print X.Y() # first one that indicates refresh
Test 2
>>> from X import Y
>>> print Y()
Test 2
>>> # Finally get what we were after
En Python, una vez que he importado un módulo X en una sesión de intérprete usando import X
, y los cambios del módulo en el exterior, puedo recargar el módulo con reload(X)
. Los cambios entonces estarán disponibles en mi sesión de intérprete.
Me pregunto si esto también es posible cuando importo un componente Y desde el módulo X usando from X import Y
La instrucción de reload Y
no funciona, ya que Y no es un módulo en sí, sino solo un componente (en este caso, una clase) dentro de un módulo.
¿Es posible recargar componentes individuales de un módulo sin salir de la sesión de intérprete (o importar todo el módulo)?
EDITAR:
Para aclarar, la pregunta es acerca de importar una clase o función Y desde un módulo X y volver a cargar en un cambio, no un módulo Y desde un paquete X.
-
reload()
móduloX
, -
reload()
modulo importandoY
desdeX
Tenga en cuenta que la recarga no cambiará los objetos ya creados enlazados en otros espacios de nombres (incluso si sigue la guía de estilo de Alex).
En primer lugar, no deberías usar recargar, si puedes evitarlo. Pero supongamos que tiene sus razones (es decir, la depuración dentro de IDLE).
La recarga de la biblioteca no devolverá los nombres al espacio de nombres del módulo. Para hacer esto, simplemente reasigne las variables:
f = open(''zoo.py'', ''w'')
f.write("snakes = [''viper'',''anaconda'']/n")
f.close()
from zoo import snakes
print snakes
f = open(''zoo.py'', ''w'')
f.write("snakes = [''black-adder'',''boa constrictor'']/n")
f.close()
import zoo
reload(zoo)
snakes = zoo.snakes # the variable ''snakes'' is now reloaded
print snakes
Usted podría hacer esto de otras maneras. Puede automatizar el proceso buscando en el espacio de nombres local y reasignando todo lo que era del módulo en cuestión, pero creo que estamos siendo lo suficientemente malos.
Si Y es un módulo (y X un paquete), la reload(Y)
estará bien; de lo contrario, verá por qué las buenas guías de estilo de Python (como mi empleador) dicen que nunca se debe importar nada, excepto un módulo (este es uno de muchas y muy buenas razones: sin embargo, la gente sigue importando funciones y clases directamente, no importa cuánto explique que no es una buena idea ;-).
Si quieres hacer esto:
from mymodule import myobject
Haga esto en su lugar:
import mymodule
myobject=mymodule.myobject
Ahora puede usar myobject de la misma manera que estaba planeando (sin las referencias de mymodule indescriptibles y aburridas en todas partes).
Si está trabajando de forma interactiva y desea volver a cargar myobject desde mymodule, ahora puede utilizar:
reload(mymodule)
myobject=mymodule.myobject
Solo para dar seguimiento a las AlexMartelli''s y Catskul''s , hay algunos casos realmente simples pero desagradables que parecen confundir la reload
, al menos en Python 2.
Supongamos que tengo el siguiente árbol fuente:
- foo
- __init__.py
- bar.py
Con el siguiente contenido:
init.py:
from bar import Bar, Quux
bar.py:
print "Loading bar"
class Bar(object):
@property
def x(self):
return 42
class Quux(Bar):
object_count = 0
def __init__(self):
self.count = self.object_count
self.__class__.object_count += 1
@property
def x(self):
return super(Quux,self).x + 1
def __repr__(self):
return ''Quux[%d, x=%d]'' % (self.count, self.x)
Esto funciona bien sin usar reload
:
>>> from foo import Quux
Loading bar
>>> Quux()
Quux[0, x=43]
>>> Quux()
Quux[1, x=43]
>>> Quux()
Quux[2, x=43]
Pero intenta volver a cargar y no tiene efecto o corrompe las cosas:
>>> import foo
Loading bar
>>> from foo import Quux
>>> Quux()
Quux[0, x=43]
>>> Quux()
Quux[1, x=43]
>>> reload(foo)
<module ''foo'' from ''foo/__init__.pyc''>
>>> Quux()
Quux[2, x=43]
>>> from foo import Quux
>>> Quux()
Quux[3, x=43]
>>> reload(foo.bar)
Loading bar
<module ''foo.bar'' from ''foo/bar.pyc''>
>>> Quux()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "foo/bar.py", line 17, in __repr__
return ''Quux[%d, x=%d]'' % (self.count, self.x)
File "foo/bar.py", line 15, in x
return super(Quux,self).x + 1
TypeError: super(type, obj): obj must be an instance or subtype of type
>>> Quux().count
5
>>> Quux().count
6
>>> Quux = foo.bar.Quux
>>> Quux()
Quux[0, x=43]
>>> foo.Quux()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "foo/bar.py", line 17, in __repr__
return ''Quux[%d, x=%d]'' % (self.count, self.x)
File "foo/bar.py", line 15, in x
return super(Quux,self).x + 1
TypeError: super(type, obj): obj must be an instance or subtype of type
>>> foo.Quux().count
8
La única manera de asegurar que se recargara el submódulo de la bar
era reload(foo.bar)
; la única forma de acceder a la clase de Quux
recargada es alcanzarlo y extraerlo del submódulo recargado; pero el propio módulo foo
mantuvo el objeto original de la clase Quux
, presumiblemente porque usa la from bar import Bar, Quux
(en lugar de la import bar
seguida de Quux = bar.Quux
); Además, la clase Quux
se desincronizó consigo misma, lo cual es simplemente extraño.
asumiendo que usaste from X import Y
, tienes dos opciones:
reload(sys.modules[''X''])
reload(sys.modules[__name__]) # or explicitly name your module
o
Y=reload(sys.modules[''X'']).Y
algunas consideraciones:
A. si el ámbito de importación no es de todo el módulo (e, g: importar en una función), debe usar la segunda versión.
B. si Y se importa a X desde otro módulo (Z), debe volver a cargar Z, luego volver a cargar X y luego volver a cargar su módulo, incluso volver a cargar todos sus módulos (e, g: usar [ reload(mod) for mod in sys.modules.values() if type(mod) == type(sys) ]
) puede recargar X antes de recargar Z - y no actualizar el valor de Y.
from modulename import func
import sys
reload(sys.modules[''modulename''])
from modulename import func