Tkinter回调异常:matplotlib动画

时间:2018-04-20 15:18:00

标签: python matplotlib tkinter pyserial

我使用Arduino通过I2C与传感器通信。从传感器获取数据后,Arduino通过串行通信将其输出为字符串。字符串看起来像这样:

"-3.46,-8.4,4.64,7.5,35.3,4.32,-9.0,\r\n"

然后我使用Python来读取传入的数据,将其分段(丢弃\r\n),然后通过matplotlib.animation实时显示用户选择的数据集。在我的计算机上使用脚本时,它工作正常,但在尝试在另一台计算机上使用它时,我收到一个Tkinter回调异常错误。

Python脚本:

port = 'com4'       # Configure which port the Arduino is connected to.
baud = 19200        # Configure baud rate
ind  = 0            # Determine which data point you want displayed on the graph. [0-6]
import numpy as np
from matplotlib.lines import Line2D
import matplotlib.pyplot as plt
import matplotlib.animation as animation
import serial
import time
import re
import xlwt


if serial.Serial(port,baud).is_open:
    serial.Serial(port,baud).close()

ser = serial.Serial(port,baud,timeout=1)
ser.reset_input_buffer()
ser.readline()

class Scope(object):
    def __init__(self, ax, maxt=4, dt=0.04):
        self.ax = ax
        self.dt = dt
        self.maxt = maxt
        self.tdata = [-dt]
        self.ydata = [0]
        self.line = Line2D(self.tdata, self.ydata)
        self.ax.add_line(self.line)
        self.ax.set_ylim(yMin, yMax)
        self.ax.set_xlim(0, self.maxt)

    def update(self, y):
        lastt = self.tdata[-1]
        if lastt > self.tdata[0] + self.maxt:  # reset the arrays
            self.tdata = [self.tdata[-1]]
            self.ydata = [self.ydata[-1]]
            self.ax.set_xlim(self.tdata[0], self.tdata[0] + self.maxt)
            self.ax.figure.canvas.draw()

        t = self.tdata[-1] + self.dt
        self.tdata.append(t)
        tArray.append(t)
        self.ydata.append(y)
        self.line.set_data(self.tdata, self.ydata)
        return self.line,


def emitter():
    while True:
        val = ser.readline()
        allData = val.split(",")
        yArray.append(allData[:-1])     # discarding return line characters from the serial read.

        yield allData[ind]

fig, ax = plt.subplots()
scope = Scope(ax)

# pass a generator in "emitter" to produce data for the update func
ani = animation.FuncAnimation(fig, scope.update, emitter, interval=10,blit=True)
plt.show()

print yArray

错误讯息:

Exception in Tkinter callback
Traceback (most recent call last):
  File "C:\Python27\lib\lib-tk\Tkinter.py", line 1542, in __call__
    return self.func(*args)
  File "C:\Python27\lib\lib-tk\Tkinter.py", line 592, in callit
    func(*args)
  File "C:\Python27\lib\site-packages\matplotlib\backends\_backend_tk.py", line 88, in _on_timer
    TimerBase._on_timer(self)
  File "C:\Python27\lib\site-packages\matplotlib\backend_bases.py", line 1373, in _on_timer
    ret = func(*args, **kwargs)
  File "C:\Python27\lib\site-packages\matplotlib\animation.py", line 1481, in _step
    still_going = Animation._step(self, *args)
  File "C:\Python27\lib\site-packages\matplotlib\animation.py", line 1217, in _step
    self._draw_next_frame(framedata, self._blit)
  File "C:\Python27\lib\site-packages\matplotlib\animation.py", line 1237, in _draw_next_frame
    self._post_draw(framedata, blit)
  File "C:\Python27\lib\site-packages\matplotlib\animation.py", line 1260, in _post_draw
    self._blit_draw(self._drawn_artists, self._blit_cache)
  File "C:\Python27\lib\site-packages\matplotlib\animation.py", line 1275, in _blit_draw
    a.axes.draw_artist(a)
  File "C:\Python27\lib\site-packages\matplotlib\axes\_base.py", line 2622, in draw_artist
    a.draw(self._cachedRenderer)
  File "C:\Python27\lib\site-packages\matplotlib\artist.py", line 55, in draw_wrapper
    return draw(artist, renderer, *args, **kwargs)
  File "C:\Python27\lib\site-packages\matplotlib\lines.py", line 738, in draw
    self.recache()
  File "C:\Python27\lib\site-packages\matplotlib\lines.py", line 656, in recache
    yconv = self.convert_yunits(self._yorig)
  File "C:\Python27\lib\site-packages\matplotlib\artist.py", line 200, in convert_yunits
    return ax.yaxis.convert_units(y)
  File "C:\Python27\lib\site-packages\matplotlib\axis.py", line 1526, in convert_units
    ret = self.converter.convert(x, self.units, self)
  File "C:\Python27\lib\site-packages\matplotlib\category.py", line 65, in convert
    unit.update(values)
AttributeError: 'NoneType' object has no attribute 'update'

我已将其指向if中的scope.update声明,具体为:

self.tdata = [self.tdata[-1]]
self.ydata = [self.ydata[-1]]

因为在评论这些行时,程序会继续运行(虽然没有意义,因为它没有更新图表)。

工作系统上运行python --version && pip freeze会导致:

Python 2.7.13
appdirs==1.4.3
certifi==2018.1.18
chardet==3.0.4
configobj==5.0.6
cycler==0.10.0
Cython==0.28
decorator==4.0.11
enum34==1.1.6
et-xmlfile==1.0.1
functools32==3.2.3.post2
future==0.16.0
idna==2.6
ipython-genutils==0.2.0
iso8601==0.1.12
jdcal==1.3
matplotlib==2.0.2
mpltools==0.2.0
mpmath==0.19
nose==1.3.7
numpy==1.13.0rc1+mkl
openpyxl==2.4.7
packaging==16.8
panda==0.3.1
pandas==0.22.0
patsy==0.5.0
pyparsing==2.2.0
pyperclip==1.5.27
pyserial==3.4
python-dateutil==2.6.0
pytz==2017.2
PyVISA==1.8
pywin32==221
PyYAML==3.12
requests==2.18.4
scikit-learn==0.19.1
scipy==0.19.0
seaborn==0.8.1
six==1.10.0
sklearn==0.0
sympy==1.0
traitlets==4.3.2
urllib3==1.22
vispy==0.5.3
xlwt==1.3.0

... 非工作系统

Python 2.7.13
backports.functools-lru-cache==1.5
cycler==0.10.0
et-xmlfile==1.0.1
jdcal==1.3
kiwisolver==1.0.1
matplotlib==2.2.2
numpy==1.13.1
openpyxl==2.4.8
pyparsing==2.2.0
pyserial==3.4
python-dateutil==2.7.2
pytz==2018.4
six==1.11.0
xlwt==1.3.0

2 个答案:

答案 0 :(得分:1)

<强>解决!

通过将非工作计算机的matplotlib版本从2.2.2恢复为2.0.2,问题就会消退。虽然这解决了这个问题,但我不确定这个问题背后的根本原因是什么。

答案 1 :(得分:0)

我在尝试对完全相同的异常回调进行故障排除时遇到了该线程。我发现问题是由matplotlib函数引起的,该函数用于包含类似字符串对象的更新图。也许这是matplotlib中某个地方的错误,但是我已经通过在附加到ydata数组之前将y值转换为int来解决了它。对于您的代码,我的实现是:self.ydata.append(int(y)) 也许float可以像ImportanceOfBeingErnest所建议的那样工作