Python:控制台无限循环,栈空间溢出

2 投票
1 回答
1112 浏览
提问于 2025-04-18 18:13

下面是实现的代码。不过,每次我在控制台输入内容时,都会出现这个错误:

        while executing
    "::tcl::Bgerror {out of stack space (infinite loop?)} {-code 1 -level 0 -errorcode NONE -errorinfo {out of stack space (infinite loop?)
        while execu..."
    error in background error handler:

out of stack space (infinite loop?)

这个错误是因为另一个应用程序(Matplotlib GUI)正在使用它,它会创建一个ConsoleInput,然后使用最近的用户输入。

为什么会出现这个错误,我该如何修复ConsoleInput?有没有办法检查是否有待处理的输入,而不是一直循环读取?

import threading


class ConsoleInput(threading.Thread):

    def __init__(self):
        threading.Thread.__init__(self)
        self.daemon = True
        self.exit = False
        self.most_recent_entry = None

    def run(self):
        while not self.exit:
            self.most_recent_entry = raw_input()

这里是使用控制台输入的GUI相关部分:

def __init__(self):
    self.console_input = ConsoleInput()
    self.console_input.start()
    self.run()

def run(self):
    self.figure = plt.figure(figsize=(16, 8))
    self.figure.canvas.set_window_title(self.title)
    self.gen_data()
    plt.connect('button_press_event', self.on_fig_update_event)
    plt.connect('motion_notify_event', self.on_fig_update_event)
    plt.tight_layout()
    plt.show()

def gen_data(self):
    if self.console_input.most_recent_entry:
        print self.console_input.most_recent_entry:

1 个回答

2

[编辑] 根据你提供的新信息……试试这个解决方案 (原始解决方案在下面找到)

class SomeClass:
    def __init__(self):
        #this stuff is bad dont do it
        #self.console_input = ConsoleInput()
        #self.console_input.start()
        self.run()
    def on_console(self,evt):

        print "data = ",self.var.get()

    def run(self):
        self.figure = plt.figure(figsize=(16, 8))
        self.figure.canvas.set_window_title("a title")
        plt.subplots_adjust(bottom=0.25) # Make space for stuff
        plt.plot([1,2,3],[5,5,6])
        #add stuff to our frame
        self.var = StringVar() #hold user variable
        b = Button(self.figure.canvas.get_tk_widget(),text="Update Chart!")
        b.pack(side="bottom",fill="both",padx=4,pady=1)
        slider = Entry(self.figure.canvas.get_tk_widget(),textvariable = self.var)
        slider.pack(side="bottom", fill='both',  padx=4, pady=4)
        b.bind("<Button-1>",self.on_console)
        plt.show()

有两件事情可能是你在寻找的……但一般来说,图形界面的程序不应该读取标准输入……

一个更好的解决方案是通过图形界面获取信息,像这样:

from matplotlib import pyplot as plt
import tkSimpleDialog
class SomeClass:
    def __init__(self):
        #this stuff is bad dont do it
        #self.console_input = ConsoleInput()
        #self.console_input.start()
        self.run()
    def on_console(self,evt):
        data = tkSimpleDialog.askstring("HELLO?","You?")
        print data
        #do something with the data (and self.figure perhaps)
    def run(self):
        self.figure = plt.figure(figsize=(16, 8))
        self.figure.canvas.set_window_title("a title")
        plt.connect('key_release_event', self.on_console)
        plt.show()

不过,如果你真的想使用控制台输入,可能应该使用cmd模块。

import cmd
from matplotlib import pyplot as plt
class SomeClass:
        def __init__(self):
            #this stuff is bad dont do it
            #self.console_input = ConsoleInput()
            #self.console_input.start()
            self.run()
        def on_console(self,evt):
            print "EVT:",evt
            MyCmdInterface(self).cmdloop()
        def run(self):
            self.figure = plt.figure(figsize=(16, 8))
            self.figure.canvas.set_window_title("a title")
            plt.connect('key_release_event', self.on_console)
            plt.show()

class MyCmdInterface(cmd.Cmd):
    """Simple command processor example."""
    prompt="CMD:"
    def __init__(self,guiInst):
        print "MPL Interactive Command Interface! type HELP for help."
        cmd.Cmd.__init__(self)
        self.gui = guiInst
    def do_HELP(self,line):
        print "Some Help Message"
    def do_SET(self, line):
        assert "=" in line,"SET COMMANDS REQUIRE <varName>=<valName>"
        var,val = line.split("=",1)
        #do something
    def do_NEWDATA(self,line):
        newdata = map(float,line.split(","))
        print "SET latest_values = %s"%newdata
        self.gui.latest_values = newdata
        #do something with new data

    def do_EOF(self, line):
        return True
    #aliases for exit
    do_EXIT = do_exit = do_QUIT = do_quit = do_DONE = do_done = do_EOF

if __name__ == '__main__':
    s = SomeClass()
    s.run()

这也展示了一个简短可运行的代码示例是什么样的。

撰写回答