2011-07-18 6 views
5

Lavorare in Python. Ho una funzione che legge da una coda e crea un dizionario basato su alcuni tag XML nel record letto dalla coda e restituisce questo dizionario. Io chiamo questa funzione in un ciclo per sempre. Il dizionario viene riassegnato ogni volta. La memoria precedentemente utilizzata dal dizionario viene liberata ad ogni riassegnazione, oppure viene resa orfana e alla fine causa problemi di memoria?I dizionari Python hanno liberato tutta la memoria quando vengono riassegnati?

def readq(): 
    qtags = {} 
    # Omitted code to read the queue record, get XML string, DOMify it 

    qtags['result'] = "Success" 
    qtags['call_offer_time'] = get_node_value_by_name(audio_dom, 'call_offer_time') 
    # More omitted code to extract the rest of the tags 

    return qtags 

while signals.sigterm_caught == False: 
    tags = readq() 
    if tags['result'] == "Empty": 
     time.sleep(SLEEP_TIME) 
     continue 
    # Do stuff with the tags 

Così, quando ho riassegnare i tag ogni volta in quel ciclo, sarà la memoria utilizzata dalla precedente assegnazione ottenere liberato prima di essere assegnati dal nuovo incarico?

+0

Che ne dici se aggiungo "del tag" alla fine del mio ciclo per cancellarlo esplicitamente? – codebunny

+0

Grazie a tutti per aver reso chiaro ciò che sta accadendo. – codebunny

risposta

8

La memoria di un oggetto viene liberata se può essere provata (dalla conoscenza dell'implementazione del linguaggio in fase di esecuzione) che non è più possibile accedervi e il garbage collector lo considera adatto per creare una raccolta. Questo è il minimo assoluto e non dovresti più assumerlo. E di solito non dovresti avere a preoccuparti di più.

Più In pratica, può essere liberato ad certo punto nel tempo tra l'ultimo riferimento (dove "riferimento" non è limitato ai nomi di perimetro, ma può essere qualsiasi cosa che rende l'oggetto reachable) essendo rimosso e la memoria si sta esaurendo. Non deve essere liberato dall'implementazione di Python che esegue il codice, può anche lasciare la pulizia della memoria sul sistema operativo e dimenticare qualsiasi finalizzatore e così via. Si noti che può verificarsi un ritardo notevole tra l'ultimo riferimento e l'utilizzo della memoria effettivamente in calo. Ma come accennato in precedenza, la maggior parte delle implementazioni fanno di tutto per evitare un eccessivo uso della memoria se c'è un problema da raccogliere.

Ancora più praticamente, è possibile eseguirlo su CPython (l'implementazione di riferimento), che viene sempre utilizzato e in modo ottimale utilizza sempre il conteggio dei riferimenti (aumentato con un GC reale per gestire i riferimenti ciclici), quindi a meno che non ci sia un riferimento ciclico (relativamente raro e il tuo codice non sembra averli, ma può verificarsi ad es. in strutture di tipo grafico) verrà liberato non appena l'ultimo riferimento ad esso viene cancellato/sovrascritto. Naturalmente, altre implementazioni non sono prevedibili: PyPy ha una mezza dozzina di raccoglitori di rifiuti diversi, tutti tranne uno che rientrano nel paragrafo precedente.

+0

+1 Risposta piacevole e completa. –

2

No, verrà liberato DOPO che il nuovo oggetto è stato creato.

Affinché il conteggio dei riferimenti scenda sul vecchio oggetto, è necessario puntare il tags al nuovo oggetto. Ciò accade dopo i ritorni readq, quindi per lo meno entrambi gli oggetti esisteranno dall'inizio di qtags = {} dopo tags = readq().

Come indicato da @delnan, subito dopo il tags è stato puntato al nuovo oggetto, il vecchio verrà liberato dal garbage collector poiché non vi è più un riferimento.

+0

In realtà, come ha affermato @delnan, a meno che non si possa assumere un'implementazione specifica, l'oggetto non * deve * essere raccolto "presto". –

+0

Capisco, ma penso che dal momento in cui il poster ha dovuto chiedere se la memoria __ever__ viene liberata, 'presto' è una buona approssimazione della verità. – agf

1

Solitamente Python può tenere il passo con qualsiasi cosa tu passi. Il raccoglitore di dati inutili usato in Python utilizza il conteggio dei riferimenti, quindi l'utilizzo della memoria dovrebbe essere costante, non vedrai alcun picco nella memoria. Quando rimuovi un riferimento (assegna la variabile a qualcos'altro), il garbage collector restituisce la memoria nel "heap", se lo desideri. Quindi non preoccuparti per la memoria. Ho eseguito simulatori eseguendo test per ore di riscrittura delle variabili, ma l'utilizzo della memoria rimane pressoché invariato. Sarà liberato quando gli assegni un nuovo dizionario.

Problemi correlati