Baron Yugovich
Baron Yugovich

Reputation: 4307

Python: Console with infinite loop, getting out of stack space

The implementation is pasted below. However, each time I actually input something in the console, I get this error:

        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?)

This is used by another application(Matplotlib GUI), that instantiates ConsoleInput, and then uses the most recent user entry for itself.

Why is this error happening, and how can I fix ConsoleInput? Is there a way to check if there is pending input, and only read then, rather than loop constantly?

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()

Here is the relevant part of the GUI that's using the console input:

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:

Upvotes: 2

Views: 1113

Answers (1)

Joran Beasley
Joran Beasley

Reputation: 113978

[edit] Based on new information you have provided ... try this solution (original solutions found below)

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()

two things something like this maybe what you are looking for ... but in general you really shouldnt be reading stdin with gui programs ...

A much better solution is to get the info from the gui something like

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()

however if you really want to use console input you should probably use the cmd module

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()

this also demonstrates what a short runnable code example looks like

Upvotes: 2

Related Questions