Recargar el módulo provoca resultados diferentes

Durante las pruebas, agregué un comando de recarga a mis casos de prueba para poder cambiar el código en varios lugares diferentes sin tener que recargar todo manualmente y noté que las recargas parecían afectar los resultados de las pruebas.

Esto es lo que hice:

import mymodule
import mymodule.rules as rules

def testcase():
    reload(mymodule)
    reload(rules)

    # The rest of the test case

Todo funciona bien así, o cuando se comentan ambas recargas, pero cuando comento la segunda recarga, los resultados de la prueba son diferentes. ¿Hay algo que sucede durante el proceso de recarga que no conozco que requiera recargar todos los scripts de un módulo una vez que se recarga el módulo? ¿Hay alguna otra explicación?

No estoy seguro de si esto es relevante, pero las reglas son un script separado dentro del paquete que incluye esta línea:

from mymodule import Rule

preguntado el 27 de julio de 12 a las 17:07

Una de las razones por las que el estado global es malo es que dificulta las pruebas unitarias. -

2 Respuestas

La información en su pregunta es bastante vaga y su terminología no es estándar. Desde

rules es un script separado dentro de mymodule.

infiero que mymodule es en realidad un paquete, y parece que no importa automáticamente rules al momento de la importación. Esto implica que después de ejecutar

import mymodule

no habrá mymodule.rules, pero después de ejecutar

import mymodule.rules as rules

el módulo rules se importará al espacio de nombres de mymodule. (Nota al margen: la última línea de código generalmente se escribe como from mymodule import rules.)

Después de ejecutar la primera reload() declaración, obtendrá una copia fresca de mymodule, que no contendrá mymodule.rules – esto solo se volverá a crear después del segundo reload() .

Tuve que hacer muchas conjeturas para esta respuesta, así que podría haberme equivocado. Él reload() declaración tiene muchas sutilezas, como se puede ver en su documentación, por lo que es mejor usarlo solo si está familiarizado con la maquinaria de importación de Python.

(Otra nota al margen: si rule.py reside dentro del paquete mymodule, como parece ser su configuración, debe usar una importación relativa allí. En vez de

from mymodule import Rule

deberías hacer

from . import Rule

Yo tambien recomiendo from __future__ import absolute_import para reglas de importación más transparentes).

Respondido 27 Jul 12, 17:07

Si recargar el paquete significa que el módulo de reglas no está incluido, ¿no debería generarse una excepción cuando el código intenta llamar a una función desde las reglas? - mofeta

Además, tienes razón, quiero decir paquete. Y la razón por la que no usé "reglas de importación de mymodule", como lo haría normalmente, es porque recargar (reglas) no funciona después de ese tipo de importación. - mofeta

La regla es solo una clase. rules.py es un conjunto de funciones que devuelven algunos objetos Rule de uso común. Sin embargo, investigaré absolute_import, gracias. - mofeta

@Skunkwaffle: lo más probable es que termine con dos instancias de un solo módulo de alguna manera, pero no sé lo suficiente sobre su configuración para estar seguro. Y sí, recibiría un mensaje de error si algo intentara acceder mymodule.rules mientras no está allí, pero ¿cómo debería saber que no lo hiciste? - Sven Marnach

Creo que podrías tener razón en dos casos. Preferiría no pegar todo mi código aquí (hay bastante), pero veré si puedo encontrar más detalles para incluir para aclarar aún más la estructura. Además, pensé en explicar que obtuve resultados del caso de prueba con ambas configuraciones implicadas que no hubo errores. Mis disculpas si eso no fue claro. - mofeta

No estoy seguro exactamente de qué está causando su problema, pero creo que puede estar haciendo un mal uso reload().

Según el documentos, reload() detectarás

Vuelva a cargar un módulo previamente importado.

Sin embargo, si está ejecutando esto en un caso de prueba, no habrá ningún cambio en el módulo entre el momento en que lo importa y el momento en que lo vuelve a cargar, ¿verdad? Para que haya cambios, creo que tendría que cambiar esos archivos a medida que se ejecuta el caso de prueba, lo que probablemente no sea una buena idea.

Respondido 27 Jul 12, 18:07

No estoy cambiando el archivo durante las ejecuciones, pero los estoy cambiando entre ejecuciones. Dado que el caso de prueba ya realizó su propia importación, necesitaba tener una forma de actualizar los cambios sin tener que salir del intérprete y comenzar de nuevo. Parece que incluso si vuelvo a cargar el caso de prueba, usa la versión anterior del código del módulo a menos que incluya las declaraciones de recarga en la prueba misma. - mofeta

¿No sería más fácil iniciar un nuevo intérprete para el caso de prueba? $ python testcase.py? De esa manera, puede estar seguro de que lo que sea que tenga en su intérprete actual no interfiere con el caso de prueba. - sam musmann

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.