python - meaning - ¿Cuándo debería usarse Flask.g?
flask wikipedia (2)
saw que g
pasará del contexto de solicitud al contexto de la aplicación en Flask 0.10, lo que me hizo confundir el uso previsto de g
.
Mi comprensión (para Flask 0.9) es que:
-
g
vive en el contexto de la solicitud, es decir, se crea de nuevo cuando comienzan las solicitudes, y está disponible hasta que finaliza -
g
está destinado a ser utilizado como un "pizarrón de solicitud", donde puedo poner cosas relevantes para la duración de la solicitud (es decir, establecer un indicador al comienzo de la solicitud y manejarlo al final, posiblemente desde unabefore_request
/after_request
par) - además de mantener el estado de nivel de solicitud,
g
puede y debe usarse para la gestión de recursos, es decir, para mantener conexiones de bases de datos, etc.
¿Cuáles de estas oraciones ya no son ciertas en Flask 0.10? ¿Puede alguien señalarme un recurso para discutir las razones del cambio? ¿Qué debo usar como una "pizarra de solicitudes" en Flask 0.10? ¿Debo crear mi propia aplicación / extensión específica de subprocesos proxy local e insertarla en la pila de contexto antes de la before_request
? ¿Cuál es el punto de la administración de recursos en el contexto de la aplicación, si mi aplicación vive por un tiempo largo (no como una solicitud) y por lo tanto los recursos nunca se liberan?
Como una adición a la información en este hilo: también me ha confundido un poco el comportamiento del flask.g
, pero algunas pruebas rápidas me han ayudado a aclararlo. Esto es lo que probé:
from flask import Flask, g
app = Flask(__name__)
with app.app_context():
print(''in app context, before first request context'')
print(''setting g.foo to abc'')
g.foo = ''abc''
print(''g.foo should be abc, is: {0}''.format(g.foo))
with app.test_request_context():
print(''in first request context'')
print(''g.foo should be abc, is: {0}''.format(g.foo))
print(''setting g.foo to xyz'')
g.foo = ''xyz''
print(''g.foo should be xyz, is: {0}''.format(g.foo))
print(''in app context, after first request context'')
print(''g.foo should be abc, is: {0}''.format(g.foo))
with app.test_request_context():
print(''in second request context'')
print(''g.foo should be abc, is: {0}''.format(g.foo))
print(''setting g.foo to pqr'')
g.foo = ''pqr''
print(''g.foo should be pqr, is: {0}''.format(g.foo))
print(''in app context, after second request context'')
print(''g.foo should be abc, is: {0}''.format(g.foo))
Y aquí está la salida que da:
in app context, before first request context
setting g.foo to abc
g.foo should be abc, is: abc
in first request context
g.foo should be abc, is: abc
setting g.foo to xyz
g.foo should be xyz, is: xyz
in app context, after first request context
g.foo should be abc, is: xyz
in second request context
g.foo should be abc, is: xyz
setting g.foo to pqr
g.foo should be pqr, is: pqr
in app context, after second request context
g.foo should be abc, is: pqr
Como dijo el Y4Kman más arriba, "cada solicitud empuja un nuevo contexto de aplicación". Y como dicen los Flask , el contexto de la aplicación "no se compartirá entre las solicitudes". Ahora, lo que no se ha establecido explícitamente (aunque supongo que está implícito en estas declaraciones), y lo que muestra claramente mi prueba, es que nunca debe crear explícitamente múltiples contextos de solicitud anidados dentro de un contexto de aplicación, porque flask.g
(y ) no tiene ninguna magia por lo que funciona en los dos "niveles" diferentes de contexto, con diferentes estados que existen de forma independiente en los niveles de solicitud y solicitud.
La realidad es que el "contexto de la aplicación" es potencialmente un nombre bastante engañoso, porque app.app_context()
es un contexto por solicitud, exactamente el mismo que el "contexto de solicitud". Piénselo como un "contexto literario de solicitud", solo requerido en el caso de que necesite algunas de las variables que normalmente requieren un contexto de solicitud, pero no necesita acceder a ningún objeto de solicitud (por ejemplo, al ejecutar operaciones DB por lotes en un guión de shell). Si intenta ampliar el contexto de la aplicación para abarcar más de un contexto de solicitud, estará buscando problemas. Entonces, en lugar de mi prueba anterior, en su lugar debes escribir código como este con los contextos de Flask:
from flask import Flask, g
app = Flask(__name__)
with app.app_context():
print(''in app context, before first request context'')
print(''setting g.foo to abc'')
g.foo = ''abc''
print(''g.foo should be abc, is: {0}''.format(g.foo))
with app.test_request_context():
print(''in first request context'')
print(''g.foo should be None, is: {0}''.format(g.get(''foo'')))
print(''setting g.foo to xyz'')
g.foo = ''xyz''
print(''g.foo should be xyz, is: {0}''.format(g.foo))
with app.test_request_context():
print(''in second request context'')
print(''g.foo should be None, is: {0}''.format(g.get(''foo'')))
print(''setting g.foo to pqr'')
g.foo = ''pqr''
print(''g.foo should be pqr, is: {0}''.format(g.foo))
Lo cual dará los resultados esperados.
speakerdeck.com/mitsuhiko/advanced-flask-patterns-1 , como se vincula por Markus, explica algunos de los cambios en g
en 0.10:
-
g
ahora vive en el contexto de la aplicación. - Cada solicitud empuja un nuevo contexto de aplicación , borrando el antiguo, por lo que
g
puede utilizarse para establecer indicadores por solicitud sin cambiar el código. - El contexto de la aplicación aparece una vez que se llama a la petición de
teardown_request
. (La presentación de Armin explica que esto se debe a que cosas como la creación de conexiones debefore_request
datos son tareas que configuran el entorno para la solicitud y no deben manejarse dentro debefore_request
yafter_request
)