Python telnet 读取问题
Posted
技术标签:
【中文标题】Python telnet 读取问题【英文标题】:Python telnet read issue 【发布时间】:2018-03-30 06:09:32 【问题描述】:我试图从一个不发送结束行或特殊字符的 telnet 服务器读取,以告诉 python telnet 客户端读取应该完成。然后将此数据发送到 tkinter 文本输入小部件,我希望它在其中不断更新从 telnet 服务器发送的新数据。存在的问题是我无法找到一种“不阻塞循环”的方法来从 telnet 服务器读取。谢谢
def Telnet_Client(self):
HOST = self.TelnetHostIP
tn = telnetlib.Telnet(HOST)
tn.write("s")
tnrecv = tn.read_until(">", timeout=1)
self.R.insert(tk.END, tnrecv)
tn.close()
我使用了 read_some() 但我没有获得所有数据,并且 read_until(">", timeout=1) 会阻止代码,因为它永远不会得到结束行或停止读取的命令
【问题讨论】:
为什么不使用线程? 但是如何停止永无止境的读取过程? 如果读取在后台线程上,您不需要需要停止读取;这就是使用线程的全部意义——线程可以阻塞直到有东西要读取,而你的其他线程继续运行。 但是,从后台线程与 tkinter GUI 对话是不可能的,而且解决方法有点麻烦,所以它不像听起来那么容易完全。 哇,这么多。我没想到会这么复杂。我打算切换到 python 3,但我遇到了 telnetlib 问题,所以现在我想要更改为 python 3 【参考方案1】:这个问题的传统解决方案是产生一个后台线程来与套接字对话。该后台线程可以阻止读取,并且不会影响任何其他线程。但是,这有一个问题:tkinter
不是线程安全的,尝试从后台线程更新您的Entry
小部件将失败。 (根据您的平台,它可能会崩溃、阻止程序,或者最糟糕的是,间歇性工作并导致大量神秘错误。)
您可以搜索一些解决方法,但都不是很好。
基本思想是让后台线程向主线程发送消息——例如,通过将消息发布到主线程可以检查的queue.Queue
(使用get(block=False)
)。但是,在您移动鼠标时,每次通过事件循环进行检查可能过于频繁,但在您空闲时却不够频繁 - 如果您要求 tkinter 每 N 秒触发一次检查,这可能会使笔记本电脑无法运行睡觉。此外,做到这一点并不完全困难,但也不是微不足道的。
曾经有一个很好的库将这一切尽可能地包装起来,称为mtTkinter
,但它很久以前就被废弃了。几年前我ported it to Python 3,但最终没有使用它,因此该版本也被有效地放弃了。它可能会起作用,但我没有做出任何承诺。
这个解决方案的优点是它非常简单:import mttkinter as tkinter
,添加一个threading.Thread(target=telnet_loop)
,再做几个小改动,你就完成了……如果它有效的话。
更现代的解决方案是使用asyncio
(或像 Twisted 这样的前身或像 Curio 这样的竞争对手)。
您可以从 Tkinter 事件循环中驱动 asyncio
循环,它比任何线程解决方法都干净得多。 A 有现成的库可以为您完成。 (我不知道现在的情况,但我用的是几年前原来的asyncio-tkinter
。)
唯一的问题是您不能使用telnetlib
,因为它不是为asyncio
设计的。但几乎可以肯定还有更现代的 Telnet 库。 (通过快速搜索,我找到了telnetlib3
,看起来很有希望,但我知道的不够多,无法推荐它。)
当然,此解决方案需要重写您的大部分网络代码——但您没有太多代码,而且它无法正常工作,所以这似乎不是一个太大的悲剧。与此同时,您的 tkinter 代码应该只需要进行一行更改。
【讨论】:
以上是关于Python telnet 读取问题的主要内容,如果未能解决你的问题,请参考以下文章