此时我仍然是GUI和网络编程的菜鸟,所以我希望这将是一个非常简单的修复。我对tkinter和asyncore模块有一个非常基本的了解,他们在每个模块中都构建了一些程序,但是我在一个程序中一起使用它们时遇到了麻烦。我整理了一个完整的UI,发现我无法实现任何重要的异步网络功能。为了简单起见,我将程序解构为最简单的形式,以说明我遇到的基本问题。下面是代码:
from Tkinter import *
import asyncore, socket
class Application(object):
def __init__(self, root):
mainFrame = Frame(root)
mainFrame.grid(column=1, row=1, columnspan=3, rowspan=1)
mainButton = Button(mainFrame, text='Click', command=self.makeSocket)
mainButton.grid(column=2, row=1, columnspan=1, rowspan=1, pady=7, padx=40)
def makeSocket(self):
clientSocket()
class clientSocket(asyncore.dispatcher):
def __init__(self):
asyncore.dispatcher.__init__(self)
self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
self.connect(("XXX.XXX.XXX.XXX", XXXX))
print 'init works'
def handle_connect(self):
print 'connect works'
root = Tk()
myApp = Application(root)
root.after_idle(asyncore.loop)
root.mainloop()
因此,当我运行程序并单击按钮时,我得到字符串'init works',表示clientSocket对象已初始化并且连接成功。但是,handle_connect方法不会运行。如果我实现handle_read方法并在服务器上执行命令(将数据发送回客户端),则不会调用此方法。我认为存在一些阻止asyncore循环自行运行的一般问题。我意识到tkinters事件循环可能是罪魁祸首,但我的印象是after_idle方法允许在GUI空闲时处理非Tkinter事件。是tkinter事件循环仍然会导致问题还是其他东西?
答案 0 :(得分:2)
这里有几个问题,我不确定它是哪一个。
asyncore.loop是一个在事情正常工作时永不返回的函数。 root.mainloop可能是一个在关闭窗口之前永远不会返回的函数。所以事情可能会出错,因为在某个时刻,一个循环会被另一个循环挨饿一段时间。
(顺便说一句,这就是为什么我不喜欢试图通过替换主循环并将其替换为事件驱动系统来使其使用更容易的框架 - 它可以很好地工作,直到您需要将这些系统中的两个或更多一起使用,事情可能会变得混乱。)
但是,您可以限制asyncore.loop迭代的次数。试试这个:
def poll_asyncore_once():
asyncore.loop(count=1)
root.after_idle(poll_asyncore_once)
您可能还希望在循环调用中添加超时值,不到一秒钟。
然而,我仍然认为即使GUI因为你进入asyncore循环而最终缺乏事件,连接也会最终完成。这意味着其他东西出了问题,asyncore可能会在connect()方法中引发异常而TK正在吞噬它。尝试在clientSocket中添加一个异常处理程序。 init ,看看你怎么做。
答案 1 :(得分:0)
请参阅JacobHallén的this recipe,了解如何将asyncore和Tkinter结合使用(基本上通过线程技巧)。 (它也在Python Cookbook的第一版印刷版中扩展为配方9.6,在第二版中扩展为11.4)。