Domanda

Ho un interprete Python incorporato in un'applicazione. L'applicazione richiede molto tempo per avviarsi e non ho la possibilità di riavviare l'interprete senza riavviare l'intera applicazione. Quello che vorrei fare è essenzialmente salvare lo stato dell'interprete e tornare facilmente a quello stato.

Ho iniziato memorizzando i nomi di tutti i moduli in sys.modules con cui l'interprete python ha iniziato e quindi cancellando tutti i nuovi moduli da sys.modules quando richiesto. Ciò sembra rendere l'interprete pronto a reimportare gli stessi moduli anche se li ha già importati in precedenza. Tuttavia, questo non sembra funzionare in tutte le situazioni, come l'uso di classi singleton e metodi statici, ecc.

Preferirei non incorporare un altro interprete all'interno di questo interprete se questo può essere evitato, poiché la facilità di essere in grado di utilizzare l'API delle applicazioni andrà persa (oltre a includere un leggero colpo di velocità che immagino).

Quindi, qualcuno conosce un modo in cui posso memorizzare lo stato dell'interprete e poi tornare a questo in modo che possa far fronte a tutte le situazioni?

Grazie,

Dan

È stato utile?

Soluzione

Prova questo codice dalle ricette di ActiveState: http://code.activestate.com/recipes/572213 /

Estende il sottaceto in modo che supporti il ??decapaggio di qualsiasi cosa definita nella console della shell. Teoricamente dovresti essere in grado di decapare il modulo principale , secondo la loro documentazione:

import savestate, pickle, __main__
pickle.dump(__main__, open('savestate.pickle', 'wb'), 2)

Altri suggerimenti

Suggerirei di affrontare il problema della causa principale.

  

" L'applicazione richiede molto tempo   avviare e non ne ho la possibilità   riavviare l'interprete senza   riavviare l'intera applicazione "

Dubito che sia vero al 100%. Se l'applicazione complessiva è il risultato di un atto del Congresso, okay, non può essere cambiata. Ma se l'applicazione complessiva è stata scritta da persone reali, dovrebbe essere possibile trovare e spostare il codice per riavviare l'interprete Python. È più economico, più semplice e più affidabile di qualsiasi cosa che potresti fare per risolvere il problema.

  

memorizzando i nomi di tutti i moduli in sys.modules con cui l'interprete python ha iniziato e quindi eliminando tutti i nuovi moduli da sys.modules quando richiesto. Ciò sembra rendere l'interprete pronto a reimportare gli stessi moduli anche se li ha già importati prima.

L'approccio di ricarica del modulo può essere fatto funzionare in alcune circostanze, ma è un po 'peloso. In sintesi:

  • È necessario assicurarsi che tutti i moduli che hanno dipendenze reciproche siano ricaricati contemporaneamente. Pertanto, qualsiasi modulo 'x' che 'importa y' o 'da y import ...' deve essere eliminato da sys.modules contemporaneamente al modulo 'y'.

  • Questo processo dovrà essere protetto con un lucchetto se l'app o qualsiasi altro modulo attivo utilizza thread.

  • Qualsiasi modulo che lascia ganci puntati su se stesso in altri moduli non può essere ricaricato utilmente poiché i riferimenti al vecchio modulo rimarranno nel codice non ricaricato / non ricaricabile. Ciò include elementi come hook di eccezione, segnali, filtri di avvertenze, codifiche, patch di scimmie e così via. Se inizi a ricaricare allegramente moduli contenenti codice di altre persone potresti essere sorpreso dalla frequenza con cui fanno cose del genere, con il risultato potenzialmente di errori sottili e curiosi.

Quindi per farlo funzionare devi avere dei confini ben definiti tra i moduli interdipendenti - "è stato importato al momento dell'avvio iniziale" probabilmente non è abbastanza buono - e per assicurarsi che siano ben incapsulati senza dipendenze inaspettate come il patching delle scimmie.

Questo può essere basato su una cartella, quindi ad esempio qualsiasi cosa in / home / me / myapp / lib può essere ricaricata come unità, lasciando soli altri moduli - specialmente il contenuto dello stdlib in es. /usr/lib/python2.x/ che in genere non è affidabile per ricaricare. Ho del codice per questo in un wrapper di ricarica webapp ancora inedito, se necessario.

Infine:

  • È necessario conoscere un po 'le caratteristiche interne di sys.modules, in particolare che lascia un gruppo di valori "Nessuno" per indicare importazioni relative non riuscite. Se non li elimini contemporaneamente ai tuoi altri valori del modulo, il tentativo successivo di importare un modulo può (a volte) finire per importare "Nessuno", causando errori di confusione.

Questo è un brutto dettaglio di implementazione che potrebbe cambiare e rompere la tua app in una futura versione di Python, ma questo è il prezzo per giocare con sys.modules in modi non supportati.

Un approccio molto caotico e soggetto a bug potrebbe essere un modulo c che copia semplicemente la memoria in un file in modo che possa essere ricaricato la volta successiva. Ma dal momento che non riesco a immaginare che funzionerebbe sempre correttamente, il decapaggio sarebbe un'alternativa?

Se sei in grado di rendere tutti i tuoi moduli selezionabili di quanto dovresti essere in grado di decapare tutto nei globi () in modo che possa essere ricaricato di nuovo.

Se si conoscono in anticipo i moduli, le classi, le funzioni, le variabili, ecc ... in uso, è possibile scaricarli su disco e ricaricarli. Non sono sicuro che sia il modo migliore per affrontare il problema se l'ambiente contiene molte incognite. Tuttavia, può essere sufficiente mettere in salamoia i locali e i locali.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top