pyplot崩溃在macOS中的plt.figure()上

时间:2017-05-17 16:35:27

标签: python django macos matplotlib tcl

我反复得到RuntimeError:当我调用plt.figure()时,主线程不在主循环中。

这是一个图表功能,可以根据django webapp中的用户数据创建图表。

我在python 3.4中看到IDLE的警告,我的Tcl / Tk版本可能不稳定,链接到http://www.python.org/download/mac/tcltk/以获取更多信息,但这并没有提供任何有关如何确定内容的指导我在venv中运行的版本,或者如何更新venv中的版本。

此错误仅发生在我的Mac OS环境中。

不确定我是否使用matplotlib错误,或者我是否需要更新我的环境。如果我需要更新,我不知道如何在虚拟环境中进行更新。

代码:

def visualize(frictionloss):
    """
    Input: an instance of a FrictionLoss model,
    Return: a bar chart of the losses in b64 encoded image
    """
    # 6 bars
    ind = np.arange(6)
    width = .65

    # load psi lost in each section to a bar to show
    losses1 = (frictionloss.ug_1_loss,
              frictionloss.ug_2_loss,
              frictionloss.riser_loss,
              frictionloss.bulk_main_loss,
              frictionloss.cross_main_loss,
              frictionloss.head_1_loss)

    # additionally, show each head loss to later stack on top
    losses2 = (0, 0, 0, 0, 0, frictionloss.head_2_loss)
    losses3 = (0, 0, 0, 0, 0, frictionloss.head_3_loss)
    losses4 = (0, 0, 0, 0, 0, frictionloss.head_4_loss)
    losses5 = (0, 0, 0, 0, 0, frictionloss.head_5_loss)
    losses6 = (0, 0, 0, 0, 0, frictionloss.head_6_loss)

    # backend here has to be forced to one thread, otherwise it misbehaves
    lock = Lock()
    lock.acquire()
    frictionFig = plt.figure()
    lock.release()

    # build a stack of bar charts on top of each other,
    # the first 5 bars only get used in chart 1,
    # the last bar gets used in all 6 to show each head in the branch line
    ax = frictionFig.add_subplot(111)
    rects1 = ax.bar(ind, losses1, width, color='#e05757')
    rects2 = ax.bar(ind, losses2, width, color='#a38080', bottom=losses1)
    rects3 = ax.bar(ind, losses3, width, color='#efcece', bottom=losses2)
    rects4 = ax.bar(ind, losses4, width, color='#d69393', bottom=losses3)
    rects5 = ax.bar(ind, losses5, width, color='#fc6767', bottom=losses4)
    rects6 = ax.bar(ind, losses6, width, color='#a38080', bottom=losses5)

    # set axes and labels
    ax.set_ylabel('Lost Pressure (psi)')
    ax.set_xticklabels(('',
                       'UG 1',
                       'UG 2',
                       'Riser',
                       'Bulk Main',
                       'Cross Main',
                       'Heads'))

    # remove the frame lines
    ax.spines['top'].set_visible(False)
    ax.spines['right'].set_visible(False)
    ax.spines['left'].set_visible(False)
    ax.spines['bottom'].set_visible(False)

    # Converts the graph into a string to be sent as a context variable
    buffer = BytesIO()
    frictionFig.savefig(buffer, format='png')
    buffer.seek(0)
    graph = quote(b64encode(buffer.getvalue()))

    return graph

错误:

Environment:


Request Method: GET
Request URL: http://127.0.0.1:8000/densitycurve/

Django Version: 1.11
Python Version: 3.6.1
Installed Applications:
['django.contrib.admin',
 'django.contrib.sites',
 'registration',
 'django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.messages',
 'django.contrib.staticfiles',
 'home',
 'hydrograph',
 'densitycurve',
 'storage',
 'frictionloss',
 'flowtest',
 'pipeweight',
 'result',
 'useraccount',
 'watersupply',
 'seismichanger',
 'widget_tweaks',
 'crispy_forms']
Installed Middleware:
['django.middleware.security.SecurityMiddleware',
 'django.contrib.sessions.middleware.SessionMiddleware',
 'django.middleware.common.CommonMiddleware',
 'django.middleware.csrf.CsrfViewMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
 'django.contrib.messages.middleware.MessageMiddleware',
 'django.middleware.clickjacking.XFrameOptionsMiddleware']



Traceback:

File "/Users/Mark/Desktop/Professional/FSC/water/WATER/ENV/lib/python3.6/site-packages/django/core/handlers/exception.py" in inner
  41.             response = get_response(request)

File "/Users/Mark/Desktop/Professional/FSC/water/WATER/ENV/lib/python3.6/site-packages/django/core/handlers/base.py" in _legacy_get_response
  249.             response = self._get_response(request)

File "/Users/Mark/Desktop/Professional/FSC/water/WATER/ENV/lib/python3.6/site-packages/django/core/handlers/base.py" in _get_response
  187.                 response = self.process_exception_by_middleware(e, request)

File "/Users/Mark/Desktop/Professional/FSC/water/WATER/ENV/lib/python3.6/site-packages/django/core/handlers/base.py" in _get_response
  185.                 response = wrapped_callback(request, *callback_args, **callback_kwargs)

File "/Users/Mark/Desktop/Professional/FSC/water/WATER/ENV/lib/python3.6/site-packages/django/contrib/auth/decorators.py" in _wrapped_view
  23.                 return view_func(request, *args, **kwargs)

File "/Users/Mark/Desktop/Professional/FSC/water/WATER/densitycurve/views.py" in densitycurve
  160.          (graph, outputText) = processData(densityInstance, request)

File "/Users/Mark/Desktop/Professional/FSC/water/WATER/densitycurve/views.py" in processData
  204.  densityFigure = plt.figure()

File "/Users/Mark/Desktop/Professional/FSC/water/WATER/ENV/lib/python3.6/site-packages/matplotlib/pyplot.py" in figure
  535.                                         **kwargs)

File "/Users/Mark/Desktop/Professional/FSC/water/WATER/ENV/lib/python3.6/site-packages/matplotlib/backends/backend_tkagg.py" in new_figure_manager
  81.     return new_figure_manager_given_figure(num, figure)

File "/Users/Mark/Desktop/Professional/FSC/water/WATER/ENV/lib/python3.6/site-packages/matplotlib/backends/backend_tkagg.py" in new_figure_manager_given_figure
  98.         icon_img = Tk.PhotoImage(file=icon_fname)

File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/tkinter/__init__.py" in __init__
  3539.         Image.__init__(self, 'photo', name, cnf, master, **kw)

File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/tkinter/__init__.py" in __init__
  3495.         self.tk.call(('image', 'create', imgtype, name,) + options)

Exception Type: RuntimeError at /densitycurve/
Exception Value: main thread is not in main loop

2 个答案:

答案 0 :(得分:2)

更新:

使用非交互式后端(reference)可以解决此问题。我没有发现这个答案,因为改变django中的后端有点棘手。

标准方法是在模块顶部写字​​:

models.py:

import matplotlib  
matplotlib.use('Agg')  
from matplotlib import pyplot as plt  

但是在django中,matplotlib可能会在你的模块导入之前导入,而后端只能设置一次!因此,要可靠地更改后端,必须通过导入matplotlib在django设置文件中执行此操作:

settings.py:

import matplotlib
matplotlib.use('Agg')

答案 1 :(得分:0)

错误消息本身告诉您错误:GUI的主循环(用于处理来自OS的大量事件; GUI是复杂的)必须位于程序的主线程中。在内部,这是因为它管理特定于线程的资源的方式,但您使用的编程API是单线程的。

如果您愿意,可以在其他线程中执行任何非GUI处理(例如,将数据转换为正确的格式),但UI调用只需要来自主线程。