Django-debug-toolbar-line-profiler只显示一行输出,没有内容

11 投票
2 回答
2207 浏览
提问于 2025-04-18 00:34

我有一个树莓派放在一个偏远的地方。它连接着一个小的自制电路和一个温度探头。我已经设置了树莓派来做几件事情:

  • 每小时运行一次cron任务,读取温度并将其存储到本地的sqlite数据库中
  • 运行一个Nginx网页服务器
  • 运行一个uwsgi应用服务器
  • 提供一个简单的Django应用

在这个Django应用中,我有一个简单的视图,做了以下几件事:

  1. 从数据库获取最近的300条温度记录
  2. 把这些记录放到一个Pandas的DataFrame
  3. 使用Matplotlib生成一个漂亮的SVG图表,显示最近的温度变化
  4. 填充一个简单的模板,展示这个SVG图表和最近温度记录的小HTML表格。

渲染这个视图大约需要30秒。真是太长了。所以我想看看是什么原因导致这么慢。我猜可能是生成图形的工作太多了。但为了确认,我想做一些性能分析。

我通过pip安装了django-debug-toolbardjango-debug-toolbar-line-profiler

我根据文档尽量配置了它们。特别是,我设置了:

DEBUG = True
TEMPLATE_DEBUG = DEBUG
DEBUG_TOOLBAR_PATCH_SETTINGS = False

MIDDLEWARE_CLASSES = (
    'debug_toolbar.middleware.DebugToolbarMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    # Uncomment the next line for simple clickjacking protection:
    # 'django.middleware.clickjacking.XFrameOptionsMiddleware',
)

DEBUG_TOOLBAR_PANELS = (
    'debug_toolbar.panels.versions.VersionsPanel',
    'debug_toolbar.panels.timer.TimerPanel',
    'debug_toolbar.panels.settings.SettingsPanel',
    'debug_toolbar.panels.headers.HeadersPanel',
    'debug_toolbar.panels.sql.SQLPanel',
    'debug_toolbar.panels.staticfiles.StaticFilesPanel',
    'debug_toolbar.panels.templates.TemplatesPanel',
    'debug_toolbar.panels.cache.CachePanel',
    'debug_toolbar.panels.signals.SignalsPanel',
    'debug_toolbar.panels.logging.LoggingPanel',
    'debug_toolbar.panels.redirects.RedirectsPanel',

    'debug_toolbar_line_profiler.panel.ProfilingPanel',
)

另外,INTERNAL_IPS也设置得很正确。

我使用基于类的视图来构建我的视图。它看起来是这样的:

from django.views.generic import TemplateView
from XXXX.models import TempReading, TempSeries
import numpy as np
import pandas as pd
import matplotlib
from matplotlib.figure import Figure
from matplotlib.backends.backend_agg import FigureCanvasAgg as FigureCanvas
import seaborn as sbn
import StringIO

class TestView(TemplateView):
    template_name = 'XXXX/test.html'

    def get_context_data(self, **kwargs):
        upstairs = TempSeries.objects.get(name='Upstairs')
        upstairstemps = upstairs.tempreading_set.all().order_by('-timestamp')[:300]

        frame = pd.DataFrame(list(upstairstemps.values()))
        frame.set_index('timestamp', inplace=True)

        # matplotlib.rcParams['svg.fonttype'] = 'none'

        fig = Figure()
        ax = fig.add_subplot(1,1,1)
        frame['value'].plot(ax=ax)
        ax.get_xaxis().grid(color='w', linewidth=1)
        ax.get_yaxis().grid(color='w', linewidth=1)

        fig.set(facecolor='w')
        canvas = FigureCanvas(fig)

        imgdata = StringIO.StringIO()
        canvas.print_svg(imgdata)

        imgstr = imgdata.getvalue()

        context = super(TestView, self).get_context_data(**kwargs)
        context['svgtext'] = imgstr
        context['htmltable'] = frame[:5].to_html()

        return context

我最想分析的代码是get_context_data

当我加载页面时,调试工具确实显示出来了。性能分析面板也显示了。但我看到的只是:

{method 'disable' of '_lsprof.Profiler' objects}

这是页面首次加载时的截图: enter image description here

这是在性能分析页面的样子: enter image description here

看起来根本没有进行“行级分析”!我本来期待能看到我基于类的视图中每一行的执行时间。特别是get_context_data函数中的每一行。发生了什么?任何帮助都非常感谢。


4月2日更新

作为测试,我写了一个不使用基于类的视图的虚拟视图。结果似乎很好。以下是新的非基于类的视图:

def testview2(request):
    df = pd.DataFrame({'a': np.random.randn(10), 'b': np.random.randn(10)})
    htmltable = df.to_html()
    context = {}
    context['htmltable'] = htmltable

    return render(request, 'XXXX/test2.html', context)

这在性能分析面板中产生了以下结果: enter image description here

所以这似乎工作得很好。我是不是遗漏了关于debug-toolbar-line-profiler与基于类的视图如何配合使用的一些细节?文档中提到它会分析类中所有不以下划线开头的方法。这是错误的吗?

2 个回答

0

既然你是在某个芯片上运行这个程序,我强烈建议你把服务器端的工作尽量简化,把复杂的逻辑处理放到客户端去做。

没错,JavaScript的能力和Python差不多,而且这些处理不会在你的服务器上进行。所有的图形绘制,甚至模板渲染,都应该放到客户端去做。这样做肯定能减少在像芯片这样的设备上加载页面的时间。

至于调试,为什么不先在真正的电脑上调试一下,然后再移到树莓派上呢?你可以加一些简单的日志记录,来标记你想要检查的部分。

1

我发现当我给我的视图加上了 @csrf_exempt 这个装饰器后,就出现了问题;一旦把它去掉,性能分析工具就正常工作了。

我不太清楚为什么会导致这个问题,但这样做解决了我的困扰。

撰写回答