我正在开发一个使用Twisted和wxReactor的程序。每当我尝试退出应用程序时,它都会挂起,我必须强行退出它。我的wxPython OnClose()事件确实调用了reactor.stop(),据我所知应该解决这个问题。在我寻求答案时,我遇到了这张票:www.twistedmatrix.com/trac/ticket/3948。
我已经尝试过页面上列出的补丁,没有运气。我已经在这个问题上待了两个星期了,而且非常绝望:)。
为您提供有关此项目的所有背景信息:它是一个免费软件客户端,它使用套接字连接到多人游戏服务器(目前播放Monopoly和Uno)。如果你运行它,你会立即注意到没有图形。这是因为该客户端仅通过语音合成和声音效果提供音频反馈。该项目的目标受众是视障游戏玩家。
要测试此问题,请运行python rsg.py(可以在src文件夹中找到。如果您需要知道,我使用的是Python 2.6.5)。在终端中,您将看到程序生成的输出(主要是服务器发送给客户端的输出)。一旦看到“Connection Made”行(应在运行后很快打印),请尝试关闭程序(通过单击X)。客户端将挂起几秒钟,然后您将需要强制退出应用程序(在Ubuntu上,它会询问我是否要强制退出应用程序)。
我确实知道它为什么不能正常退出。当我通过gdb运行它时,两个线程没有退出。奇怪的是,如果服务器关闭连接,那么我退出程序,它会正常工作。
我非常感谢所有的帮助。提前谢谢。
修改 因为我被要求提供我的问题的基本演示,所以它是:
import wx
import sys
from twisted.internet import wxreactor
wxreactor.install()
# import t.i.reactor only after installing wxreactor:
from twisted.internet import reactor
from twisted.protocols.basic import LineReceiver
from twisted.internet.protocol import ClientFactory
class ZGPClient(LineReceiver):
"""Our client object."""
def lineReceived(self, datavar):
"As soon as any data is received"
print datavar
class EchoFactory(ClientFactory):
protocol = ZGPClient
def startedConnecting(self, connector):
global conn
conn = connector
print 'Started to connect.'
def sendData(self, data=""):
conn.transport.write(data.encode("ascii", "ignore") + "\n")
class main_window(wx.Frame):
def __init__(self, parent, id, title):
super(main_window, self).__init__(parent, id, title, style=wx.DEFAULT_FRAME_STYLE)
self.Bind(wx.EVT_CLOSE, self.OnClose)
self.Show(True)
def OnClose(self, event):
reactor.stop()
sys.exit()
if __name__ == "__main__":
app = wx.App()
frame = main_window(None, wx.ID_ANY, "RS Games Client - No Game")
reactor.registerWxApp(app)
sockObj = EchoFactory()
reactor.connectTCP("rsgamesmonserver.webhop.org", 3555, sockObj)
reactor.run()
app.MainLoop()
答案 0 :(得分:1)
这对你有用:
def OnClose(self, evt):
# ugly hack until wxreactor is patched:
reactor._stopping = True
reactor.callFromThread(_threadedselect.ThreadedSelectReactor.stop, reactor)
答案 1 :(得分:0)
我的一个项目遇到了同样的问题。 我只需要删除以下代码:
当您使用扭曲时,反应堆正在驱动您的应用程序。通过停止反应堆,您也可以停止整个应用程序。问题可能是由sys.exit()引发的异常引起的(如果确实如此,我不确定),因为reactor正在捕获所有异常并向控制台报告。
请记住,当你使用扭曲或其他类似的框架时,你必须以一种不同的方式思考(Inversion of control)。另外,我建议您在Asynchronous Programming and Twisted上阅读这个精彩的教程系列。
反应器必须在其run方法中调用MainLoop()。在您的代码中,您将启动两个主循环,并且您需要关闭主窗口两次才能退出。