使用pyplot.close()会导致烧瓶应用崩溃

时间:2018-07-05 10:02:11

标签: python-3.x matplotlib flask

我正在用Flask制作一个网络应用,该应用在一个网页上显示不同的pyplot图表。以下是我用来创建不同绘图的代码,然后将它们作为以base64编码的png图像返回。

import pandas as pd
import numpy as np
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error
import matplotlib.pyplot as plt
import io
import base64


def simple_plot():
    img = io.BytesIO()
    np.random.seed(196801)
    x = np.random.rand(50)
    y = np.random.rand(50)
    plt.plot(x, y)
    plt.savefig(img, format='png')
    img.seek(0)
    lp = base64.b64encode(img.getvalue()).decode()
    plt.close()
    return lp

def scatter_plot():
    img = io.BytesIO()
    np.random.seed(19680801)
    x = np.random.rand(30)
    y = np.random.rand(30)
    colors = np.random.rand(30)
    area = np.pi * (15 * np.random.rand(30)) ** 2
    plt.scatter(x, y, s=area, c=colors, alpha=0.5)
    plt.savefig(img, format='png')
    img.seek(0)
    sp = base64.b64encode(img.getvalue()).decode()
    plt.close()
    return sp


def linear_reg_plot():
    data = pd.read_csv("data/clean_df.csv")
    lm = LinearRegression()
    img = io.BytesIO()
    X = data[['highway-mpg']]
    Y = data['price']
    lm.fit(X, Y)
    predict = np.around(np.array(lm.predict(X)))
    intercept = lm.intercept_
    slope = lm.coef_
    plt.plot(X, predict)
    plt.savefig(img, format='png')
    img.seek(0)
    plot = base64.b64encode(img.getvalue()).decode()
    plt.close()
    x = data['highway-mpg'].values.tolist()
    y = data['price'].values.tolist()
    result = {
        'X': x[:50],
        'Y': y[:50],
        'Predicted': predict[:50],
        'intercept': intercept,
        'slope': slope,
        'msqe': mean_squared_error(y, predict),
        'r2': lm.score(X, predict),
        'chart': plot
    }
    return result

如果我不使用plt.close(),则会导致所有图形变为相同(在所有图形上绘制相同类型的数据)。但是在使用他的plt.close()之后,它会显示正确的图,但是现在我遇到了这个错误,这导致flask应用程序崩溃了,并且有一个消息框说Python崩溃了。 遵循调试器显示的错误:

127.0.0.1 - - [05/Jul/2018 14:55:04] "GET /dashboard HTTP/1.1" 200 -
Exception ignored in: <bound method Image.__del__ of <tkinter.PhotoImage object at 0x000000644962F0F0>>
Traceback (most recent call last):
  File "E:\ProgramData\Anaconda3\Lib\tkinter\__init__.py", line 3501, in __del__
    self.tk.call('image', 'delete', self.name)
RuntimeError: main thread is not in main loop
Exception ignored in: <bound method Image.__del__ of <tkinter.PhotoImage object at 0x0000006449638048>>
Traceback (most recent call last):
  File "E:\ProgramData\Anaconda3\Lib\tkinter\__init__.py", line 3501, in __del__
    self.tk.call('image', 'delete', self.name)
RuntimeError: main thread is not in main loop
Exception ignored in: <bound method Image.__del__ of <tkinter.PhotoImage object at 0x00000064495AAA20>>
Traceback (most recent call last):
  File "E:\ProgramData\Anaconda3\Lib\tkinter\__init__.py", line 3501, in __del__
    self.tk.call('image', 'delete', self.name)
RuntimeError: main thread is not in main loop
Exception ignored in: <bound method Image.__del__ of <tkinter.PhotoImage object at 0x00000064495D5C50>>
Traceback (most recent call last):
  File "E:\ProgramData\Anaconda3\Lib\tkinter\__init__.py", line 3501, in __del__
    self.tk.call('image', 'delete', self.name)
RuntimeError: main thread is not in main loop
Exception ignored in: <bound method Image.__del__ of <tkinter.PhotoImage object at 0x00000064495B61D0>>
Traceback (most recent call last):
  File "E:\ProgramData\Anaconda3\Lib\tkinter\__init__.py", line 3501, in __del__
    self.tk.call('image', 'delete', self.name)
RuntimeError: main thread is not in main loop
Exception ignored in: <bound method Image.__del__ of <tkinter.PhotoImage object at 0x0000006448E629E8>>
Traceback (most recent call last):
  File "E:\ProgramData\Anaconda3\Lib\tkinter\__init__.py", line 3501, in __del__
    self.tk.call('image', 'delete', self.name)
RuntimeError: main thread is not in main loop
Exception ignored in: <bound method Image.__del__ of <tkinter.PhotoImage object at 0x0000006448EC8940>>
Traceback (most recent call last):
  File "E:\ProgramData\Anaconda3\Lib\tkinter\__init__.py", line 3501, in __del__
    self.tk.call('image', 'delete', self.name)
RuntimeError: main thread is not in main loop
Exception ignored in: <bound method Image.__del__ of <tkinter.PhotoImage object at 0x0000006448E69160>>
Traceback (most recent call last):
  File "E:\ProgramData\Anaconda3\Lib\tkinter\__init__.py", line 3501, in __del__
    self.tk.call('image', 'delete', self.name)
RuntimeError: main thread is not in main loop
Tcl_AsyncDelete: async handler deleted by the wrong thread

下图显示了正在显示的图以及错误: Python crash error

1 个答案:

答案 0 :(得分:3)

在行前

import matplotlib.pyplot as plt

添加

import matplotlib
matplotlib.use('agg')

当前,matplotlib正在访问连接到GUI事件循环并导致意外行为的“ tkagg”后端。普通的“ agg”后端根本不连接到GUI。