Estoy tratando de integrar Flask con Dill para volcar/cargar sesiones de Python en el lado del servidor. El siguiente código tiene dos funciones, la primera establece el valor de x en cero e importa la biblioteca de datetime y hora. El segundo incrementa x en 1 y obtiene la marca de tiempo.
La primera función volca la sesión y la segunda función la carga.
En el volcado, el archivo pickle se genera correctamente, pero no puedo reutilizar x ni obtener la marca de tiempo.
Este es el error cuando trato de ejecutar x = x + 1 en la segunda función:
UnboundLocalError: local variable 'x' referenced before assignment¿Se puede usar eneldo con Flask? ¿Necesito un enfoque diferente?
El código:
from flask import Flask from dill import dump_session, load_session app = Flask(__name__) app.config['SECRET_KEY'] = 'super secret' session_file = '/tmp/session.pkl' @app.route('/start_counter') def start_counter(): import datetime x = 0 dump_session(filename = session_file) return 'New counter started!' @app.route('/count') def count(): load_session(filename = session_file) x = x + 1 now = datetime.datetime.now() dump_session(filename = session_file) return str(x) + '-' + str(now) Para simplificar las cosas, necesita una estructura de datos para mantener el estado de su aplicación. Usaría un dict porque es simple, pero también puedes definir una clase para eso.
La manera fácil (y tediosa) es llamar a state = dill.load('filename') y dill.dump(object,'filename') cada vez que necesite el estado de su aplicación.
Esto funcionará si su aplicación es pequeña. Si necesita mantener un estado de aplicación adecuado, debe usar una base de datos.
No hay problemas de compatibilidad con Dill y Flask.
Cuando llamas a dill.dump_session() guarda el estado de __main__ .
Pero, cuando aumenta x en la función count() , no está definido porque Dill no lo guardó.
Una manera fácil de ver eso es poner un punto de breakpoint() antes de x = x + 1 o imprimir el contenido dentro de una cláusula try..except :
try: print(x) except ee: print(ee) pass; x = x + 1 Entonces, no funcionó porque la variable x no estaba definida en __main__ sino en el alcance de la función start_counter() y dill.load_session() restaura las cosas en __main__ .
__main__ ?Veamos que usando un Repl:
~/$ python Python 3.8.10 (tags/v3.8.10:3d8993a, May 3 2021, 11:48:03) [MSC v.1928 64 bit (AMD64)] on win32 Type "help", "copyright", "credits" or "license" for more information. >>> dir() ['__annotations__', '__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__'] Perfecto. Tenemos un intérprete de python vacío. Ese dir() muestra lo que tenemos en __main__ .
Ahora cargaremos algunas bibliotecas, asignaremos una variable y definiremos una función solo porque podemos:
>>> import pandas, numpy, dill, pickle, json, datetime >>> foo = "bar" >>> def functionWithUglyName(): ... print("yep") >>> dir() ['__annotations__', '__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__', 'datetime', 'dill', 'foo', 'functionWithUglyName', 'json', 'numpy', 'pandas', 'pickle']``` Bien. Esa cosa __main__ parece más poblada.
Ahora guardemos la sesión y salgamos de Repl:
>>> dill.dump_session('session_01') >>> exit()¿Qué sucede cuando cargamos la sesión con `dill.load_session()'?
Abramos otro Repl para descubrirlo:
>>> dir() ['__annotations__', '__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__']Está bien. Solo otro intérprete de python vacío ...
Carguemos la sesión y veamos qué sucede:
>>> import dill >>> dill.load_session('session_01') >>> dir() ['__annotations__', '__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__', 'datetime', 'dill', 'foo', 'functionWithUglyName', 'json', 'numpy', 'pandas', 'pickle'] Cargó el contenido de __main__ como se esperaba. Espera un segundo. Cargó la functionWithUglyName WithUglyName que definimos antes. ¿Es real?
>>> functionWithUglyName() yepResulta que el eneldo es muy bueno serializando cosas. La mayoría de las veces solo necesitará recoger algunos datos, pero el eneldo puede hacer mucho más... y es excelente para depurar y probar.