2010-08-26 14 views
0

J'utilise tordu avec GTK, et le code suivant fonctionne lorsqu'une connexion n'a pu être établie:python + twisted + gtk: KeyboardInterrupt provoque une variable libre?

def connectionFailed(self, reason): 
    #show a "connect failed" dialog 
    dlg = gtk.MessageDialog(
     type=gtk.MESSAGE_ERROR, 
     buttons=gtk.BUTTONS_CLOSE, 
     message_format="Could not connect to server:\n%s" % (
      reason.getErrorMessage())) 
    responseDF = defer.Deferred() 
    dlg.set_title("Connection Error") 
    def response(dialog, rid): 
     dlg.hide_all() 
     responseDF.callback(rid) 
    dlg.connect("response", response) 
    dlg.show_all() 

    self.shutdownDeferreds.append(responseDF) 

self.shutdownDeferreds est une liste de deferreds qui est mis en place afin que le réacteur ne s'arrête pas jusqu'à ce qu'ils soient tous appelés.

Maintenant, il m'est arrivé d'appuyer sur CTRL+C en même temps que la connexion a échoué. La boîte de dialogue pop-up ne, mais quand je presse Close, je reçois:

Traceback (most recent call last): 
    File "C:\Users\DrClaud\bumhunter\gui\controller.py", line 82, in response 
    dlg.hide_all() 
NameError: free variable 'dlg' referenced before assignment in enclosing scope 
Traceback (most recent call last): 
    File "C:\Users\DrClaud\bumhunter\gui\controller.py", line 82, in response 
    dlg.hide_all() 
NameError: free variable 'dlg' referenced before assignment in enclosing scope 

Toutes les idées pourquoi cela pourrait se produire?

+0

J'ai remarqué que ce gestionnaire d'erreur est très similaire à l'exemple Twisted doc/core/examples/pbgtk2.py (qui crée également un MessageDialog, se ferme sur la variable pour y appeler une méthode et appelle show_all dessus). Cependant, je n'ai pas pu déclencher la même exception. J'ai essayé de le pointer sur une adresse IP inutilisée, puis j'ai appuyé sur C-c pendant que la connexion arrivait à expiration; le processus vient juste de sortir sans exception. J'ai également essayé d'attendre que la boîte de dialogue apparaisse, puis que j'atteigne C-c; même comportement. –

+0

je vais essayer. Apparemment, ce n'est pas une condition de course dans mon code, cela arrive juste si j'appuie sur C-c après que la boîte de dialogue apparaisse. en fait, il arrive parfois même sans C-C du tout ... peut-être que j'ai trouvé un bug dans python 2.5.4? = P – Claudiu

+0

Peut être. Python a beaucoup de bugs, comme n'importe quel logiciel. :) J'ai fait mes tests avec Python 2.6.4 et PyGTK 2.16 (les versions dans Ubuntu 9.10). –

Répondre

1

Si ce pas:

def response(dialog, rid): 
    dialog.hide_all() 
    responseDF.callback(rid) 

ou vraiment, pour plus de clarté,

def response(self, rid): 
    self.hide_all() 
    responseDF.callback(rid) 

(. Je peux me tromper à ce sujet, je l'ai fait à peine une GTK) Si oui, le problème est que vous référencez dlg dans la fonction, ce qui en fait une fermeture (capture dlg de sa portée environnante). Le KeyboardInterrupt provoquera un comportement bizarre et merveilleux, car il pourrait détruire cette portée. Pouvez-vous produire un exemple complet et minimal?

+0

ah cette dernière phrase est ce que je suis curieux. Comment 'KeyboardInterrupt' peut-il détruire la portée, ce qui est exactement ce qui s'est passé ici? bonne astuce sur la façon de faire de cette fonction pas une fermeture si – Claudiu

+0

Eh bien, Python garbage-recueille des variables quand ils sont hors de portée. Si vous relancez une erreur, elle se propage dans la pile en passant par différentes portées. à mesure que chacun reste, ses variables seront détruites. Je n'ai jamais vu ce comportement particulier auparavant; peut-être quelqu'un avec plus d'expérience GTK que je vais peser dessus. – katrielalex

+1

"Eh bien, poubelle Python-recueille des variables quand elles sont hors de portée." Non - le garbage recueille * les objets * (pas les variables) quand ils ne sont plus accessibles depuis la racine. Le dialogue ici est toujours accessible, précisément parce que 'dlg' est fermé. Quelque chose de beaucoup plus étrange se passe dans cet exemple. :) –