我反复得到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
答案 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调用只需要来自主线程。