Python GTK /线程/套接字错误

时间:2010-09-11 23:23:46

标签: python multithreading sockets gtk

我正在尝试使用pyGTK,踏板和套接字构建Python应用程序。我有这个奇怪的错误,但考虑到所涉及的所有模块,我不完全确定错误在哪里。我对一些打印语句进行了一些调试,以缩小范围,我认为错误是在这段代码中的某处:

    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”,然后尝试从服务器打印数据。但是,由于没有数据,它会引发异常,但由于某些未知原因,它不会在异常块中执行代码,并且所有内容都会从那里挂起。

关于出了什么问题的任何想法?

2 个答案:

答案 0 :(得分:1)

timeout_add正在安排行动在主线程上发生 - 所以recv只是阻塞主线程(当它只是在等待数据时),因此GUI,所以,除非你设置超时或将套接字设置为非阻塞,否则没有异常。

你需要将接收委托给来自计划行动的线程,而不是反之,以获得你所追求的效果:拥有线程,例如:等待一个事件对象,并且计划的动作每500毫秒发出一次该事件的信号。

答案 1 :(得分:0)

不,显然sock.recv调用块因为套接字尚未关闭而套接字接收默认为阻塞。确保在某个时刻关闭连接。

在新线程中运行receive调用会更有意义,否则它可能会阻止GUI,因为当前实现在GUI线程中运行recv调用(使用timeout_add)。您目前正在进行此操作的方式只有在收到答案非常快且/或您必须访问小部件时才有意义。

顺便说一下,创建一个用于调用gobject.timeout_add的新线程是完全没必要的。 timeout_add()idle_add()注册指定的回调函数并立即返回。 GTK事件循环然后在超时(或idle_add的空闲状态)后自动执行回调。