wxPython:CallAfter(AppendText,string)不打印整个字符串

发布于 2024-10-30 18:34:21 字数 1277 浏览 0 评论 0原文

我有一个循环接收套接字数据并打印它的线程:

def post(self):
    while True:
        try:
            data = pickle.loads(self.sock.recv(1024))
            print data[0] % tuple(data[1])
        except (socket.error, EOFError): 
            break

然后我有一个 GUI,它将 stdout 重定向到 textctrl,如下所示:

import wx
import sys
import threading

class Redirect: 
    def __init__(self, ctrl):
        self.out = ctrl
    def write(self, string): 
        wx.CallAfter(self.out.AppendText,string)

class GUI(wx.Frame):
    def __init__(self, parent):
        self.monitor = wx.TextCtrl(self, wx.ID_ANY, \
                               style = wx.TE_MULTILINE | wx.TE_READONLY)
        redir = Redirect(self.monitor)
        sys.stdout = redir

        self.sizer = BoxSizer(wx.VERTICAL)
        self.sizer.Add(self.monitor, 1, wx.GROW | wx.ALL)
        self.SetSizer(self.sizer)
        self.Show(True)

if __name__ == "__main__":
    app = wx.App(False)
    frame = GUI(None)
    app.MainLoop()

我还有第二个接受输入的 textctrl(为了简单起见,省略了)。问题是有时 CallAfter(AppendText,string) 不会打印出整个字符串。这种情况非常罕见,但有时打印会在字符串中间突然停止,此时会打印下一个字符串(并且应用程序会在收到字符串时继续打印字符串,就像什么都没发生一样)。

我不知道是什么导致了这种行为,我试图通过在第二个 textctrl 中输入来诱发它,看看是否是导致它的原因,但即使我什么都不做,这些“部分打印”也会时不时地出现。这是怎么回事?

I have a thread that loops receiving socket data and printing it:

def post(self):
    while True:
        try:
            data = pickle.loads(self.sock.recv(1024))
            print data[0] % tuple(data[1])
        except (socket.error, EOFError): 
            break

I then have a GUI that redirects stdout to a textctrl like so:

import wx
import sys
import threading

class Redirect: 
    def __init__(self, ctrl):
        self.out = ctrl
    def write(self, string): 
        wx.CallAfter(self.out.AppendText,string)

class GUI(wx.Frame):
    def __init__(self, parent):
        self.monitor = wx.TextCtrl(self, wx.ID_ANY, \
                               style = wx.TE_MULTILINE | wx.TE_READONLY)
        redir = Redirect(self.monitor)
        sys.stdout = redir

        self.sizer = BoxSizer(wx.VERTICAL)
        self.sizer.Add(self.monitor, 1, wx.GROW | wx.ALL)
        self.SetSizer(self.sizer)
        self.Show(True)

if __name__ == "__main__":
    app = wx.App(False)
    frame = GUI(None)
    app.MainLoop()

I've also got a second textctrl that accepts input (left out for simplicity). The issue is that sometimes CallAfter(AppendText,string) is not printing out the entire string. It is very rare, but sometimes the print will just be stopped abruptly in the middle of the string, at which point the next string is printed (and the app continues printing the strings as they're received as if nothing happened).

I've no idea what's causing this behavior, I've tried to induce it by typing into the second textctrl to see if that's causing it, but even if I do nothing, these "partial prints" appear every now and then. What's going on?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

2024-11-06 18:34:21

这不是真正的答案,只是复制问题的一种方法:

import wx
import sys
import threading

def post():
    a = 0
    for stop in range(100):
        a = (a + 1) % 10
        data = str(a) * 1000 + " <END>" 
        print(data)
    for i, line in enumerate(frame.monitor.Value.split("\n")[:-1]):
        if not line.endswith(" <END>"):
            print("Invalid line %d" % (i+1))


class Redirect: 
    def __init__(self, ctrl):
        self.out = ctrl

    def write(self, string): 
        wx.CallAfter(self.out.AppendText, string)


class GUI(wx.Frame):
    def __init__(self, parent):
        wx.Frame.__init__(self, parent)
        self.monitor = wx.TextCtrl(self, wx.ID_ANY, style = wx.TE_MULTILINE | wx.TE_READONLY)
        redir = Redirect(self.monitor)
        sys.stdout = redir

        self.sizer = wx.BoxSizer(wx.VERTICAL)
        self.sizer.Add(self.monitor, 1, wx.GROW | wx.ALL)
        self.SetSizer(self.sizer)
        self.Show(True)

if __name__ == "__main__":
    app = wx.App(False)
    frame = GUI(None)
    t = threading.Thread(target=post)
    t.start()
    app.MainLoop()

当在我的设置上运行时,我得到(通常,并非总是):

Invalid line 30
Invalid line 63

我尝试使用延迟和互斥体/锁,但似乎我没有找到原因这种事还发生过。

This is not a real answer, just a way how to replicate the problem:

import wx
import sys
import threading

def post():
    a = 0
    for stop in range(100):
        a = (a + 1) % 10
        data = str(a) * 1000 + " <END>" 
        print(data)
    for i, line in enumerate(frame.monitor.Value.split("\n")[:-1]):
        if not line.endswith(" <END>"):
            print("Invalid line %d" % (i+1))


class Redirect: 
    def __init__(self, ctrl):
        self.out = ctrl

    def write(self, string): 
        wx.CallAfter(self.out.AppendText, string)


class GUI(wx.Frame):
    def __init__(self, parent):
        wx.Frame.__init__(self, parent)
        self.monitor = wx.TextCtrl(self, wx.ID_ANY, style = wx.TE_MULTILINE | wx.TE_READONLY)
        redir = Redirect(self.monitor)
        sys.stdout = redir

        self.sizer = wx.BoxSizer(wx.VERTICAL)
        self.sizer.Add(self.monitor, 1, wx.GROW | wx.ALL)
        self.SetSizer(self.sizer)
        self.Show(True)

if __name__ == "__main__":
    app = wx.App(False)
    frame = GUI(None)
    t = threading.Thread(target=post)
    t.start()
    app.MainLoop()

When ran on my setup, I get (usually, not always):

Invalid line 30
Invalid line 63

I tried playing with delays and mutexes / locks, but it seem that I did not find why this happens yet.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文