On Fri, May 28, 2010 at 01:39:43PM +0200, Alessandro Dentella wrote: > Grazie Marco per la dritta, > > On Fri, May 28, 2010 at 12:19:12PM +0200, Marco Giusti wrote: > > On Fri, May 28, 2010 at 10:25:51AM +0200, Alessandro Dentella wrote: [...] > > > > Vediamo un po' tutti i possibili problemi che possono sorgere: > > > > 1. il metodo `delete_event_cb` elimina il riferimento alla finestra ma > > il metodo può essere ancora chiamato dal padre e non essendoci più > > riferimenti a `self.w`... > > non mi è chiaro, il padre sarebbe l'istanza stessa? Eliminata 'w', che > tramite le callback aveva riferimenti (forti, direi) a 'g', g dovrebbe > sparire per me... > > Vedo che la grossa differenza fra la mia e la tua versione è nel fatto che io > ho una connect a 'delete_event' che tu non hai, entrambe però eliminiamo con > una chiamata diretta a destroy() la finestra, che quindi emette un > 'delete_event'. Quindi io passo due volte dal metodo 'delete_event_cb', la > seconda volta il metodo non ha più self.w... ho capito!
quell'esempio è solo una diversa implementazione del tuo esempio, se devi fare una comparazione con il tuo, controlla l'altro. nel secondo esempio l'unica differenza è l'attributo `self.objects` che contiene i riferimenti forti agli oggetti. > Probabimente la dipendenza dal numero di finestre create è poi dovuta a > ritardi di gtk che è alle prese con il rendering delle finestre. La 10.04 > era simulata in VirtualBox quindi più lenta e quindi mi dava l'errore già a > 3/4 finestre. credo che questo sia un effetto aleatorio, che dipende da quando il gc entra in funzione, dal SO, dalla quantità di ram, ecc. > > 2. gli unici riferimenti che hai agli oggetti `G` sono dei riferimenti > > deboli. a questo punto credo che tu debba andare a vedere come i > > riferimenti deboli siano implementati in pygtk. non sono molto preparato > > qui ma sicuramente il problema è questo. Accanto a `self.windows` > > affianca un'altra lista: `self.objects` con riferimenti forti, vedrai > > che a questo punti non hai più di questi problemi. > > > > per quanto ne so' la gestione dei riferimenti in pygtk è pensata per, ad > > eccezione di casi particolari, potersene dimenticare. nel momento in cui > > non ci sono più riferimenti python ad un oggetto gobject, questo viene > > deallocato. > > Il tutto è nato proprio perché vedo crescere a dismisura l'occupazione di > ram in una applicazione GTK e sto pensando di rimpiazzare riferimenti forti > con riferimenti deboli. Questo test era nato proprio dall'esigenza di > vedere se riuscivo a tenere la RAM sotto controllo. > > promesso che apro altre discussioni per la ram... secondo me non è il modo migliore per procedere, a meno che tu non sia certo che il memory leak dipenda proprio dalle gtk e non da un bug nel tuo programma. weakref diventa molto utile quando devi conservare in memoria dati binari di dimenzioni considerevoli come un'immagine. in quel caso ha senso usare i riferimenti deboli: se il SO richiede di liberare la memoria il riferimento viene perso ma lo si può comunque andare a recuperare i dati. es: class Img(object): _img = None @property def img(self): if self._img is None: self._img = open(self.filename).read() return self._img def __init__(self, filename): self.filename = filename > > ps. ti allego la versione modificata. > > > > pps. la gerarchia che crei è con soli due livelli, perché allora non usi > > due classi distinte? ti allego la versione modificata > > Perché nell'esempio reale alcune istanze della classe Mask gemmano altre > istanze della classe Mask, poi nell'esempio ho cambiato il look solo perché > non fosse troppo fuorviante vedere interfacce uguali. ti allego un altro esempio che forse ti spiegherà meglio. lancialo due volte, la prima così come è, la seconda volta commenta tutti i riferimenti a `self.objects` che ti ho segnato. usando le callback puoi vedere quando gli oggetti sono deallocati. infatti quando tu hai l'eccezione: AttributeError: 'G' object has no attribute 'title' puoi notare come gli attributi dell'oggetto siano stati tutti liberati. ciao m. -- C'è un'ape che se posa su un bottone di rosa: lo succhia e se ne va... Tutto sommato, la felicità è una piccola cosa. -- Trilussa, Felicità
import os import gc import sys import weakref import gtk def callback(wref): print wref obj = wref() print obj print type(obj) print dir(obj) class G(object): def __init__(self, title=''): self.windows = [] self.objects = [] # XXX: commenta qui self.title = title self.w = gtk.Window() self.w.set_title(title) self.h = gtk.HBox() self.kill_button = gtk.Button("kill") self.crea_button = gtk.Button(title and "Finestra %s" % title or "crea %s finestre" % n) self.w.add(self.h) self.h.add(self.crea_button) self.h.add(self.kill_button) self.w.show_all() self.w.connect('delete-event', self.delete_event_cb) self.kill_button.connect('clicked', self.clicked_cb) self.crea_button.connect('clicked', self.crea_molte_finestre) def delete_event_cb(self, win, ev=None): self.w.get_toplevel().destroy() del self.w def crea_molte_finestre(self, win, ev=None): if self.title: return for i in range(n): obj = G(title=str(i)) r = weakref.ref(obj, callback) self.windows += [r] self.objects.append(obj) # XXX: commenta qui def clicked_cb(self, win): if self.title: self.delete_event_cb(win) else: for g in self.windows: if g(): g().delete_event_cb(None, None) #if g: # se non usi weakref # g.delete_event_cb(None, None) self.windows = [] del self.objects[:] # XXX: commenta qui if __name__ == '__main__' : if len(sys.argv) == 2: n = int(sys.argv[1]) else: n = 10 obj = G() obj.w.connect('destroy', gtk.main_quit) try: gtk.main() except KeyboardInterrupt: sys.exit()
_______________________________________________ Python mailing list Python@lists.python.it http://lists.python.it/mailman/listinfo/python