Reputation: 4307
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
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