Mantenga las variables persistentes en la memoria entre ejecuciones del script Python

¿Hay alguna forma de mantener una variable de resultado en la memoria para no tener que volver a calcularla cada vez que ejecuto el inicio de mi script? Estoy haciendo una serie larga (5-10 segundos) de las operaciones exactas en un conjunto de datos (que estoy leyendo del disco) cada vez que ejecuto mi script. Esto no sería un gran problema ya que soy bastante bueno en el uso del editor interactivo para depurar mi código entre ejecuciones; Sin embargo, a veces las capacidades interactivas no lo cortan.

Sé que podría escribir mis resultados en un archivo en el disco, pero me gustaría evitar hacerlo si es posible. Esta debería ser una solución que genere una variable la primera vez que ejecuto el script, y lo guarda en la memoria hasta que se cierre el shell o hasta que explique explícitamente que se apague. Algo como esto:

# Check if variable already created this session in_mem = var_in_memory() # Returns pointer to var, or False if not in memory yet if not in_mem: # Read data set from disk with open('mydata', 'r') as in_handle: mytext = in_handle.read() # Extract relevant results from data set mydata = parse_data(mytext) result = initial_operations(mydata) in_mem = store_persistent(result) 

Tengo el indicio de que el módulo de archivado podría ser lo que estoy buscando aquí, pero parece que para abrir una variable de archivado tendría que especificar un nombre de archivo para el objeto persistente, por lo que no estoy seguro de si Es exactamente lo que estoy buscando.

¿Algún consejo sobre cómo dejar de lado para hacer lo que quiero que haga? ¿Alguna idea alternativa?

Puede lograr algo como esto utilizando la función de reload global para volver a ejecutar el código del script principal. Necesitará escribir un script de envoltorio que importe su guión principal, le pregunte por la variable que desea almacenar en caché, almacene en caché una copia de eso dentro del scope del módulo del guión de envoltorios, y luego, cuando lo desee (cuando presiona ENTRAR en la entrada estándar o lo que sea ), llama a reload(yourscriptmodule) pero esta vez le pasa el objeto almacenado en caché de manera que yourscript puede evitar el cálculo costoso. Aquí hay un ejemplo rápido.

wrapper.py

 import sys import mainscript part1Cache = None if __name__ == "__main__": while True: if not part1Cache: part1Cache = mainscript.part1() mainscript.part2(part1Cache) print "Press enter to re-run the script, CTRL-C to exit" sys.stdin.readline() reload(mainscript) 

mainscript.py

 def part1(): print "part1 expensive computation running" return "This was expensive to compute" def part2(value): print "part2 running with %s" % value 

Mientras se está ejecutando wrapper.py , puede editar mainscript.py , agregar un nuevo código a la función part2 y ser capaz de ejecutar su nuevo código contra el part1Cache precalculado.

Para mantener los datos en la memoria, el proceso debe seguir ejecutándose. La memoria pertenece al proceso que ejecuta el script, NO al shell. El shell no puede contener la memoria para usted.

Por lo tanto, si desea cambiar su código y mantener el proceso en ejecución, tendrá que volver a cargar los módulos cuando se modifiquen. Si alguno de los datos en la memoria es una instancia de una clase que cambia, tendrá que encontrar la manera de convertirla en una instancia de la nueva clase. Es un poco un desastre. No hay muchos idiomas que sean tan buenos para este tipo de parches en caliente (Common Lisp viene a la mente), y hay muchas posibilidades de que las cosas salgan mal.

Si solo desea conservar un objeto (o un gráfico de objeto) para futuras sesiones, el módulo de almacenamiento probablemente sea excesivo. Solo toma el objeto que te importa. Haga el trabajo y guarde el pickle si no tiene ningún archivo de pickle, o cargue el archivo de pickle si tiene uno.

 import os import cPickle as pickle pickle_filepath = "/path/to/picklefile.pickle" if not os.path.exists(pickle_filepath): # Read data set from disk with open('mydata', 'r') as in_handle: mytext = in_handle.read() # Extract relevant results from data set mydata = parse_data(mytext) result = initial_operations(mydata) with open(pickle_filepath, 'w') as pickle_handle: pickle.dump(result, pickle_handle) else: with open(pickle_filepath) as pickle_handle: result = pickle.load(pickle_handle) 

El archivador de Python es una solución de persistencia para objetos decapados (serializados) y se basa en archivos. La ventaja es que almacena objetos de Python directamente, lo que significa que la API es bastante simple.

Si realmente desea evitar el disco, la tecnología que está buscando es una “base de datos en memoria”. Existen varias alternativas, vea esta pregunta SO: base de datos en memoria en Python .

Esta es una solución dependiente del sistema operativo …

 $mkfifo inpipe #/usr/bin/python3 #firstprocess.py complicated_calculation() while True: with open('inpipe') as f: try: print( exec (f.read())) except Exception as e: print(e) $./first_process.py & $cat second_process.py > inpipe 

Esto le permitirá cambiar y redefinir las variables en el primer proceso sin copiar ni recalcular nada. Debería ser la solución más eficiente en comparación con los módulos o bases de datos de multiprocesamiento, memcached, pickle, shelve.

Esto es realmente bueno si desea editar y redefinir second_process.py de forma iterativa en su editor o IDE hasta que lo tenga todo sin tener que esperar el primer proceso (por ejemplo, inicializar un dictado grande, etc.) para ejecutar cada vez que realice una cambio.

Puedes hacer esto pero debes usar un shell de Python. En otras palabras, el shell que usa para iniciar los scripts de Python debe ser un proceso de Python. Luego, todas las variables o clases globales vivirán hasta que cierre el shell.

Mira el módulo cmd que facilita escribir un progtwig shell. Incluso puede organizar que cualquier comando que no esté implementado en su shell pase al shell del sistema para su ejecución (sin cerrar su shell). Entonces deberías implementar algún tipo de comando, prun , por ejemplo, que ejecute un script de Python usando el módulo runpy .

http://docs.python.org/library/runpy.html

Necesitaría usar el parámetro init_globals para pasar sus datos especiales al espacio de nombres del progtwig, idealmente un dict o una instancia de una sola clase.

Puede ejecutar un script persistente en el servidor a través del sistema operativo que carga / calcular, e incluso recargar / recalcar periódicamente los datos de sql en estructuras de memoria de algún tipo y luego acceder a los datos en memoria de su otro script a través de un socket.