Python GTK/线程/套接字

2024-04-26 07:49:04 发布

您现在位置:Python中文网/ 问答频道 /正文

我尝试使用pyGTK、treads和sockets构建Python应用程序。我遇到了这个奇怪的错误,但是考虑到所有涉及的模块,我不完全确定错误在哪里。我对一些print语句进行了一些调试,以缩小范围,我认为错误就在这段代码中的某个地方:

    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方法后,我在运行程序时注意到:

-最初,图形用户界面功能齐全

-然后在终端中打印以下内容:

^{pr2}$

-在终端中打印文本后,GUI将完全不起作用(按钮无法按下等),我必须强制退出以关闭应用程序

似乎是线程打印“hello”,从服务器打印数据,然后打印“return”。500毫秒后,它再次运行collectData方法,打印“hello”,然后尝试从服务器打印数据。但是,因为没有数据留下,它会引发一个异常,但是由于某种未知的原因,它不执行异常块中的代码,所有的东西都挂起。在

有什么问题吗?在


Tags: 数据方法self服务器脚本应用程序helloreturn
2条回答

不,很明显,sock.recv调用会阻塞,因为套接字尚未关闭,并且默认情况下套接字接收是阻塞的。一定要在某个时刻关闭连接。在

在新线程中运行receive调用会更有意义,否则可能会阻塞GUI,因为您当前的实现在GUI线程中运行recv调用(使用timeout_add)。你目前的做法只有在答案很快收到和/或你必须访问小部件时才有意义。在

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

timeout_add正在调度在主线程上发生的操作,因此recv只是阻塞主线程(当它只是在等待数据时)和GUI,因此,除非您设置超时或将套接字设置为非阻塞,否则没有异常。在

您需要将接收任务委托给线程,而不是viceversa,以获得您想要的效果:让线程等待一个事件对象,并让调度的动作每500毫秒发出一次该事件的信号。在

相关问题 更多 >