Python GTK/线程/套接字错误
我正在尝试使用pyGTK、踏板和套接字构建Python应用程序。我有一个奇怪的错误,但是考虑到所有涉及的模块,我不能完全确定错误在哪里。我对一些print语句进行了一些调试,以缩小范围,我认为错误就在这段代码的某个地方:Python GTK/线程/套接字错误,python,multithreading,sockets,gtk,Python,Multithreading,Sockets,Gtk,我正在尝试使用pyGTK、踏板和套接字构建Python应用程序。我有一个奇怪的错误,但是考虑到所有涉及的模块,我不能完全确定错误在哪里。我对一些print语句进行了一些调试,以缩小范围,我认为错误就在这段代码的某个地方: self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.sock.connect(("localhost", 5005)) self.collectingThread = th
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.sock.connect(("localhost", 5005))
self.collectingThread = threading.Thread(target=self.callCollect)
self.collectingThread.daemon = True
self.collectingThread.start()
def callCollect(self):
gobject.timeout_add(500, self.collectData)
def collectData(self):
print "hello"
try:
print self.sock.recv(1024)
except:
print "except"
print "return"
return True
因此,基本上我要做的是设置一个套接字,连接到一个“服务器”脚本(实际上只是本地运行的另一个python脚本),然后创建一个单独的线程来收集服务器脚本中的所有传入数据。此线程设置为每500毫秒运行一次collectData方法
将print语句插入collectData方法后,我在运行程序时注意到:
-最初,GUI功能齐全
-然后在终端中打印以下内容:
hello
**all data received from server script and printed here**
return
hello
-在终端中打印文本后,GUI将完全失去功能(按钮无法按下等),我必须强制退出以关闭应用程序
似乎正在发生的是线程打印“hello”,打印来自服务器的数据,然后打印“return”。500毫秒后,它再次运行collectData方法,打印“hello”,然后尝试从服务器打印数据。但是,由于没有数据,它会引发异常,但由于未知原因,它不会执行异常块中的代码,所有内容都挂起
知道哪里出了问题吗?不,显然,
sock.recv
调用会阻塞,因为套接字尚未关闭,默认情况下套接字接收会阻塞。确保在某个点关闭连接
在新线程中运行receive调用更有意义,否则可能会阻塞GUI,因为当前实现在GUI线程中运行recv
调用(使用timeout\u add
)。您目前的做法只有在快速收到答案和/或您必须访问小部件时才有意义
顺便说一句,创建一个新线程来调用
gobject.timeout\u add
是完全没有必要的timeout\u add()
和idle\u add()
注册指定的回调函数并立即返回。GTK事件循环会在超时后自动执行回调(或处于空闲状态,用于idle\u add
)。否,显然sock.recv
调用会阻塞,因为套接字尚未关闭,默认情况下套接字接收会阻塞。确保在某个点关闭连接
在新线程中运行receive调用更有意义,否则可能会阻塞GUI,因为当前实现在GUI线程中运行recv
调用(使用timeout\u add
)。您目前的做法只有在快速收到答案和/或您必须访问小部件时才有意义
顺便说一句,创建一个新线程来调用
gobject.timeout\u add
是完全没有必要的timeout\u add()
和idle\u add()
注册指定的回调函数并立即返回。GTK事件循环会在超时后自动执行回调(或在空闲状态下执行idle\u add
)。timeout\u add
正在调度操作在主线程上发生——因此recv
只会阻塞主线程(当它只是在等待数据时)以及GUI,因此,除非您设置超时或将套接字设置为非阻塞,否则不会出现异常
您需要将接收任务从计划的操作委派给线程,而不是viceversa,以获得您想要的效果:让线程等待事件对象,计划的动作信号是每500毫秒发生一次事件。
超时\u添加
是计划动作在主线程上发生——因此,recv
只会阻塞主线程(当它只是在等待数据时)以及GUI,所以,除非您设置超时或将套接字设置为非阻塞,否则不会出现异常
您需要将接收来自计划操作的消息委派给线程,而不是反之亦然,以获得您想要的效果:让线程(例如,等待事件对象)每隔500毫秒发送一次该事件的计划操作信号。这是“超时添加”,而不是“超时调用”.我如何明确地告诉次线程等待事件对象及其相应的信号?我查看了pyGTK教程中的不同事件,但在套接字上找不到任何内容。很抱歉,我对pyGTK非常陌生。@pythonBOI,我想到的是Python的
线程模块,而不是GTK--请看--使用x=threading.event()
创建全局事件对象x
,在创建子线程之前,通过调用x.wait()
,让子线程块等待x
,让主线程通过x.set()
(然后通过调用x.clear()
)唤醒子线程。没有必要的带套接字的连接,也没有GTK的连接,只有通用的Python线程!这是“timeout\u add”,而不是“timeout\u call”。我如何明确地告诉辅助线程等待事件对象及其相应的信号?我查看了pyGTK教程中的不同事件,但在套接字上找不到任何内容。很抱歉,我对pyGTK非常陌生。@pythonBOI,我想到的是Python的线程模块,而不是GTK--请看--使用x=threading.event()
创建全局事件对象x
,在创建子线程之前,通过调用x.wait()
,让子线程块等待x
,让主线程通过x.set()
(然后通过调用x.clear()
)唤醒子线程。没有必要的带套接字的连接,也没有GTK的连接,只有通用的Python线程!威尔