python+;扭曲的+;gtk:键盘中断导致自由变量?

python+;扭曲的+;gtk:键盘中断导致自由变量?,python,variables,gtk,scope,twisted,Python,Variables,Gtk,Scope,Twisted,我将twisted与GTK一起使用,当无法建立连接时,将运行以下代码: 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 s

我将twisted与GTK一起使用,当无法建立连接时,将运行以下代码:

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.shutdowndferreds
是一个延迟列表,设置该列表以使反应堆在全部调用之前不会停止

现在,我碰巧在连接失败的同时按下了
CTRL+C
。对话框确实弹出了,但当我按
关闭
时,我得到:

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
你知道为什么会这样吗?

不应该是:

def response(dialog, rid):
    dialog.hide_all()
    responseDF.callback(rid)
或者说,为了清楚起见

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

(我可能错了,我几乎没有做过任何GTK。)如果是这样,问题是您在函数中引用了
dlg
,这使它成为一个闭包(它从其周围范围捕获
dlg
)。
KeyboardInterrupt
会导致奇怪而奇妙的行为,因为它会破坏这个范围。

啊,后一句话是我很好奇的。
KeyboardInterrupt
如何破坏作用域,这正是这里发生的事情?关于如何使func不成为闭包的好技巧thoughWell,Python垃圾收集超出范围的变量。如果您引发错误,它将向上传播堆栈,通过各种作用域;当每一个都离开时,它的变量将被销毁。我以前从未见过这种特殊的行为;也许有人比我有更多的GTK经验,“好吧,Python垃圾收集变量,当它们超出范围。”不,它垃圾收集对象(不是变量),当它们不再可以从根访问。这里的对话框仍然可以访问,正是因为
dlg
已关闭。在这个例子中发生了更奇怪的事情。:)@让·保罗:噢:$--谢谢!我猜这与GTK事件循环的怪异有关…?你能给出一个完整的、最小的例子吗?我注意到这个错误处理程序与Twisted doc/core/examples/pbgtk2.py示例非常相似(它还创建了一个MessageDialog,关闭变量以调用方法,并调用show_all)。不过,我无法从中触发相同的异常。我试着将它指向一个未使用的IP,然后在连接超时时点击C-C;进程无一例外地退出了。我还试着等待对话框弹出,然后点击C-C;同样的行为,我试试看。显然,在我的代码中,这不是竞争条件,只是在对话框弹出后按C-C键。事实上,有时甚至在没有C-C的情况下也会发生。。。也许我在python 2.5.4中发现了一个bug=应该是。Python和任何软件一样,有很多bug。:)我用Python2.6.4和PyGTK2.16(Ubuntu9.10中的版本)进行了测试。嘿,为什么我不给它添加bounty呢?