I saw że g
ruszy z kontekstu żądanie do aplikacji w kontekście Kolby 0,10, co czyniło mnie mylić o zamierzonym wykorzystaniem g
.
W moim rozumieniu (dla Flask 0.9):
g
żyje w kontekście żądania, tj. jest tworzony od nowa, gdy żądanie zaczyna się i jest dostępny aż do jego zakończeniag
ma być używany jako "tablica żądań", na której mogę umieścić rzeczy istotne na czas trwania żądania (tj. ustawić flagę na początku żądania i obsłużyć na końcu, prawdopodobnie zbefore_request
/after_request
pair)- oprócz utrzymywania stanu poziomu żądania,
g
może i powinien być używany do zarządzania zasobami, tj. utrzymywania połączeń z bazą danych itp.
Które z tych zdań nie jest już prawdziwe w Flask 0.10? Czy ktoś może wskazać mi źródło omawiające przyczyny zmiany? Czego powinienem używać jako „tablicy żądań” w Flask 0.10 - czy powinienem utworzyć własne lokalne proxy dla wątku specyficzne dla aplikacji / rozszerzenia i wypchnąć je na stos kontekstów before_request
? Jaki jest sens zarządzania zasobami w kontekście aplikacji, jeśli moja aplikacja istnieje przez długi czas (nie jak żądanie), a zatem zasoby nigdy nie są zwalniane?
g
w wersji 0.10, w przeciwnym razie wygląda na to, że w dużej części kodu pojawią się przebiegłe błędy.flask.g
. speakerdeck.com/mitsuhiko/advanced-flask-patterns-1Odpowiedzi:
Advanced Flask Patterns , pod linkiem Markusa , wyjaśnia niektóre zmiany
g
w wersji 0.10:g
teraz żyje w kontekście aplikacji.g
nadal można go używać do ustawiania flag na żądanie bez zmiany kodu.teardown_request
wywołaniu. (Prezentacja Armina wyjaśnia, że dzieje się tak, ponieważ tworzenie połączeń DB to zadania, które konfigurują środowisko dla żądania i nie powinny być obsługiwane wewnątrzbefore_request
iafter_request
)źródło
app_ctx is None or app_ctx.app != self.app
utworzyłeś łącze, jest wartość False, stary kontekst aplikacji wydaje się być ponownie używany? Wydaje się, że to nie w porządku, ponieważ kontekst aplikacji „nie będzie współdzielony między żądaniami” ...app.app_context()
? Jeśli tak, należy zauważyć, że przyapp_context()
każdym wywołaniu tworzy nowy kontekst aplikacji - nigdy nie używa kontekstu ponownie.app_ctx is not None and app_ctx.app == self.app
Theapp_ctx = self.app.app_context()
linia jest nie wykonywane;self._implicit_app_ctx_stack.append(None)
jest wykonywany tylko w tym przypadku.RequestContext
jest pchany, więc tylko jedenAppContext
jest pchany. Ale jeśli tryb debugowania jest włączony i żądanie nie powiedzie się, Flask zapisuje kontekst , więc można go używać z debugerem .None
jest dołączany do elementu_app_ctx_stack
, więc gdy żądanie jest usuwane, wie, że nie ma jeszcze wyskakiwaćAppContext
. To samo dzieje się z klientem testowym, który zachowuje kontekst, więc można go sprawdzić.Jako dodatek do informacji w tym wątku: byłem trochę zdezorientowany zachowaniem
flask.g
, ale kilka szybkich testów pomogło mi to wyjaśnić. Oto, co wypróbowałem:A oto wynik, który daje:
Jak powiedział wcześniej theY4Kman, „Każde żądanie przesyła nowy kontekst aplikacji”. I jak docs kolb powiedzieć , kontekst aplikacji „nie będą dzielone pomiędzy żądaniami”. To, co nie zostało wyraźnie powiedziane (chociaż wydaje mi się, że wynika to z tych stwierdzeń) i co jasno pokazuje moje testy, to fakt, że nigdy nie należy jawnie tworzyć wielu kontekstów żądań zagnieżdżonych w jednym kontekście aplikacji, ponieważ
flask.g
(i co) tego nie robi. nie ma żadnej magii, dzięki której działa na dwóch różnych „poziomach” kontekstu, z różnymi stanami istniejącymi niezależnie na poziomach aplikacji i żądania.W rzeczywistości „kontekst aplikacji” jest potencjalnie dość mylącą nazwą, ponieważ
app.app_context()
jest to kontekst na żądanie , dokładnie taki sam jak „kontekst żądania” . Potraktuj to jako „kontekst żądania lite”, wymagany tylko w przypadku, gdy potrzebujesz niektórych zmiennych, które normalnie wymagają kontekstu żądania, ale nie potrzebujesz dostępu do żadnego obiektu żądania (np. Podczas wykonywania operacji wsadowych baz danych w Skrypt powłoki). Jeśli spróbujesz rozszerzyć kontekst aplikacji, aby obejmował więcej niż jeden kontekst żądania, prosisz o kłopoty. Więc zamiast mojego testu powyżej, powinieneś zamiast tego napisać taki kod z kontekstami Flaska:Co da oczekiwane rezultaty:
źródło