I have a program that has 2 very simple threads:
- One for listening to serial port
- One for a text UI
I also have a matplotlib
animation
running in my main()
. It has a scope
class that is the example from matplotlib.
When the program starts to run, it shows the plot and everything is OK. The problem is that as soon as the user enters a key, the program crashes and python exits with a fatal error.
The ui
thread has nothing to do with matplotlib
and scope
class. If I delete the code that creates the plots, the ui
thread has no problem and program runs smoothly. I also notice matplotlib
on my system uses tkinter
for creating windows.
Do you have any hints or experiences with why the matplotlib
animation
causes problem? Can't a thread be used with a matplotlib
plot
?
I am running this in a command line window in Windows7
with Python 2.7
.
matplotlib
version : 2.0.2
Tkinter
version : 8.5
Error:
Fatal Python error: GC object already tracked
This application has requested the Runtime to terminate it in an unusual way.
Please contact the application's support team for more information.
Or this error:
TclStackFree: incorrect freePtr. Call out of sequence?
This application has requested the Runtime to terminate it in an unusual way.
Please contact the application's support team for more information.
Code:
import threading
import serial
from matplotlib.lines import Line2D
import matplotlib.pyplot as plt
import matplotlib.animation as animation
class listner(threading.Thread):
def __init__(self,port):
threading.Thread.__init__(self)
self.sport=None
self.is_running=True
self.init_port(port)
def run(self):
print ' Reading from Port'
while self.is_running:
try:
self.sport.read(1)
except:
print 'Error reading port'
def init_port(self,port):
print '1'
if self.sport==None or not self.sport.is_open :
try:
self.sport = serial.Serial(port,115200)
self.sport.timeout = 1
self.sport.reset_input_buffer()
self.sport.reset_output_buffer()
self.port_open=True
except:
print " Port error Listener Initing\n",self.port_open,'\n',self.sport
else:
pass
def process(self):
pass
class ui(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
self.running = True
def run(self):
print 'Starting UI:\n'
while self.running:
print ' Enter input ''S'':\n'
user = raw_input()
def main(port):
listner_thread = None
try:
listner_thread = listner(port)
listner_thread.start();
except:
print "Listener Thread Failed To Start"
return
ui_thread=None
try:
ui_thread = ui()
ui_thread.start()
except:
print "UI Thread Failed To Start"
return
run_charts()
def run_charts():
fig, (ax1, ax2) = plt.subplots(2, 1)
scope1 = Scope(ax1)
ani1 = animation.FuncAnimation(fig, scope1.update, emit_ch1, interval=10,blit=True)
scope2 = Scope(ax2)
ani2 = animation.FuncAnimation(fig, scope2.update, emit_ch2, interval=10,blit=True)
plt.show()
def emit_ch1():
yield 0.001
def emit_ch2():
yield -0.001
class Scope(object):
def __init__(self, ax, maxt=2, dt=0.02):
self.ax = ax
self.dt = dt
self.maxt = maxt
self.tdata = [0]
self.ydata = [0]
self.line = Line2D(self.tdata, self.ydata)
self.ax.add_line(self.line)
self.ax.set_ylim(-.009, 0.009)
self.ax.set_xlim(0, self.maxt)
def update(self, y):
t = self.tdata[-1] + self.dt
self.tdata.append(t)
self.ydata.append(y)
self.line.set_data(self.tdata, self.ydata)
return self.line,
if __name__ == '__main__':
main('COM11')