2011-11-17 12 views
12

Si consideri il seguente codice nella mia applicazione WebApp2 in Google App Engine:Capire la persistenza oggetto globale in Python WSGI apps

count = 0 

class MyHandler(webapp2.RequestHandler): 

    def get(self): 

     global count 
     count = count + 1 
     print count 

Con ogni aggiornamento della pagina, gli incrementi di conteggio superiore.

vengo dal mondo PHP dove ogni richiesta era un nuovo contesto globale. Quello che capisco di stare succedendo qui è che, poiché sto usando la configurazione wsgi per WebApp2, Python non avvia un nuovo processo su ogni richiesta. Se stavo usando una configurazione cgi, d'altra parte, l'ambiente globale sarebbe nuovamente un'istanza di volta in volta, come PHP ...

Supponendo che quanto sopra è corretto (In caso contrario, per favore correggetemi) ...

  1. Come posso gestire gli scenari in cui vorrei una variabile globale che persistesse solo per la durata della richiesta? Potrei inserire una variabile di istanza nella classe RequestHandler, ma per quanto riguarda le cose come i moduli di utilità che impongo che utilizzano le vars globali per cose come la memorizzazione di un oggetto messaggio?
  2. Esiste una tecnica per reimpostare tutte le variabili o per forzare una nuova istanziazione dell'ambiente?
  3. L'ambiente globale persiste indefinitamente o si ripristina da solo a un certo punto?
  4. Qualcuno di questi GAE è specifico o la persistenza globale di wsgi funziona allo stesso modo in qualsiasi scenario server?

EDIT:

Ecco un tentativo utilizzando ThreadLocal:

count = 0 

mydata = threading.local() 
mydata.count = 0 

class MyHandler(webapp2.RequestHandler): 

    def get(self): 

     global count 
     count = count + 1 
     print count 

     mydata.count = mydata.count + 1 
     print mydata.count 

Questi inoltre incrementare le richieste su

+0

Esiste un motivo specifico per cui si tenta di archiviare dati globali al di fuori del datastore? Sembra che ciò che stai tentando potrebbe essere realizzato più facilmente con un [contatore a contrasto] (http://code.google.com/appengine/articles/sharding_counters.html). –

+0

@ Kevin- quella variabile di conteggio era solo un esempio: il mio caso reale è qualcosa di completamente diverso - sto solo cercando di capire l'ambito globale all'interno del dominio dell'applicazione. – Yarin

+0

correlati [Perché i piloni usano StackedObjectProxies invece di threading.local?] (Http://stackoverflow.com/q/1686768/95735) –

risposta

16

La tua comprensione è corretta.Se si desidera che le variabili persistano per la durata della richiesta, non è necessario renderle globalmente - trasformarle in variabili di istanza nella classe RequestHandler, accessibile come self.var. Dal momento che un nuovo RequestHandler viene istanziato per ogni richiesta, le tue variabili resteranno invariate fino a quando ne avrai bisogno. Le variabili globali sono meglio evitate a meno che non si abbia realmente bisogno di un ambito globale (al contrario di quello specifico della richiesta).

Si noti inoltre che l'app App Engine verrà eseguita su più server; i globals sono accessibili solo alle richieste all'interno dello stesso server.

+3

buon punto su più server, grazie – Yarin

4

tua analisi della situazione è corretta, una web app Python è un processo di lunga durata. Ci vuole molto tempo per avviare l'interprete Python e non viene eseguita ogni richiesta.

'del tutto possibile per creare una variabile globale che è diverso "per-request". Questo è fatto in molti framework e la gente sembra apprezzarlo. Il modo per farlo dipende dal server. La maggior parte dei server usa "un thread per richiesta" e penso che anche GAE lo faccia. Se questo è il caso, è possibile utilizzare uno threadlocal variable. Se sei preoccupato che questo valore si aggiri tra le richieste su quel thread, avrai bisogno di un codice di gestione che possa essere collegato all'inizio/alla fine di una richiesta. Il middleware WSGI è un buon posto per questo se il framework WebApp2 non fornisce un buon modo per farlo.

è solo Python, e una richiesta viene servita nel proprio thread. Da lì puoi fare ciò che desideri. Non c'è niente in Python per resettare tutte le variabili globali e generalmente non c'è alcuna garanzia (specialmente con GAE) che il processo che serve la tua richiesta sia sempre lo stesso processo, il che significa che le tue globali non dovrebbero essere utilizzate per mantenere i dati tra le richieste a meno che tu so davvero cosa stai facendo

Ci sono molti framework che forniscono già un buon supporto per farlo, quindi se WebApp2 non lo fa suggerirei di cercare altrove. Python ha molte opzioni e molte di esse funzionano su GAE.

+0

grazie. Potresti vedere le mie modifiche- Ho provato threading.local(), ma il conteggio aumenta come il mio globale. Lo sto implementando giusto? – Yarin

+0

Probabilmente le tue richieste arriveranno sullo stesso thread. La maggior parte dei server WSGI sono implementati utilizzando un pool di thread, quindi non è necessariamente un * nuovo * thread per richiesta. Non ho familiarità con il funzionamento interno di come le app WSGI dei server GAE, ma questo è quello che mi aspetterei. –

2

Nel caso della tua prima domanda, penso che potresti considerare la funzione webapp2.Request.registry. È un obbligo di memorizzare le istanze che i diversi moduli possono condividere durante la vita della richiesta.

D'altro canto è anche utile il webapp2.WSGIApplication.registry. In questo caso, le istanze rimangono tra le richieste e possono essere condivise (e riutilizzate) per qualsiasi esigenza dell'applicazione durante la vita dell'applicazione, evitando di creare istanze nell'ambito globale.