【问题标题】:How to profile a Jinja2 template?如何配置 Jinja2 模板?
【发布时间】:2015-01-04 14:17:42
【问题描述】:

我正在分析的 Flask 应用程序花费了很长时间来渲染它的 Jinja2 模板。

我安装了flask lineprofilerpanel,这很有趣,但不幸的是,我无法深入了解模板渲染以查看所有时间都花在了哪里。

分析 Jinja2 模板的最佳方法是什么?

【问题讨论】:

  • @akai:我不知道烧瓶,但它看起来像 python。 This should work.
  • 我认为在 flask-debugtoolbar 的分析器中,您可能会看到所有调用的方法。如果您手动过滤前面有 jinja2 的那些(即 ),您可能会估算出渲染时间。
  • 可能是一个相关的问题? stackoverflow.com/questions/618827/…
  • @MikeDunlavey 答案很有趣,但在这种情况下似乎没有帮助。我试过了,但堆栈跟踪以某种方式报告该过程仅在 html 行处停止 - 即 jinja2 模板中的 no-python 行 - 并且随后有一些 jinja2 内部代码,没有显示在中断之前正在呈现哪个模板行。
  • @AlexeySmirnov 虽然如果慢速函数不是来自 jinja2(例如来自烧瓶),这不起作用,但我觉得无论如何查看分析结果是“最好”的方式,也许.. .

标签: python flask profiling jinja2


【解决方案1】:

很好的问题。我通常对分析器没有太多用处,所以这是一个很好的学习借口。按照此处的示例:https://docs.python.org/2/library/profile.html#module-cProfile 我编写了一个分析 jinja 模板的简单示例。

import cProfile as profile
import pstats
import StringIO

import jinja2
import time

pr = profile.Profile()

def slow():
    time.sleep(2)
    return "Booga!"

template = jinja2.Template(r'''
    {% for i in RANGE1 %}<h1>hello world {{ i}}</h1>{% endfor %}
    {% for i in RANGE2 %}<h1>foo bar {{ i}}</h1>{% endfor %}
    {{ SLOW() }}
        '''
        )

# here is the bit we want to profile
pr.enable()
context = {"RANGE1": range(1000000), "RANGE2":range(100), "SLOW":slow}
template.render(context)
pr.disable()


s = StringIO.StringIO()
ps = pstats.Stats(pr, stream=s).sort_stats("cumulative")
ps.print_stats()
print(s.getvalue())

这是报告的一个sn-p:

         1000130 function calls in 2.448 seconds

   Ordered by: cumulative time

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    0.000    0.000    2.438    2.438 /usr/local/lib/python2.7/dist-packages/jinja2/environment.py:974(render)
        1    0.122    0.122    2.438    2.438 {method 'join' of 'unicode' objects}
  1000104    0.315    0.000    2.317    0.000 <template>:5(root)
        1    0.000    0.000    2.002    2.002 /usr/local/lib/python2.7/dist-packages/jinja2/runtime.py:169(call)
        1    0.000    0.000    2.002    2.002 profilej.py:10(slow)
        1    2.002    2.002    2.002    2.002 {time.sleep}
        2    0.010    0.005    0.010    0.005 {range}
        1    0.000    0.000    0.000    0.000 /usr/local/lib/python2.7/dist-packages/jinja2/environment.py:1015(new_context)
        1    0.000    0.000    0.000    0.000 /usr/local/lib/python2.7/dist-packages/jinja2/runtime.py:55(new_context)
        1    0.000    0.000    0.000    0.000 /usr/local/lib/python2.7/dist-packages/jinja2/runtime.py:115(__init__)
        3    0.000    0.000    0.000    0.000 {hasattr}
        1    0.000    0.000    0.000    0.000 /usr/local/lib/python2.7/dist-packages/jinja2/_compat.py:59(<lambda>)
        1    0.000    0.000    0.000    0.000 /usr/local/lib/python2.7/dist-packages/jinja2/nodes.py:81(__init__)
        3    0.000    0.000    0.000    0.000 {getattr}
        3    0.000    0.000    0.000    0.000 /usr/local/lib/python2.7/dist-packages/jinja2/runtime.py:149(resolve)
        1    0.000    0.000    0.000    0.000 /usr/local/lib/python2.7/dist-packages/jinja2/runtime.py:126(<genexpr>)
        1    0.000    0.000    0.000    0.000 {callable}
        1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}
        1    0.000    0.000    0.000    0.000 {method 'iteritems' of 'dict' objects}
        1    0.000    0.000    0.000    0.000 {isinstance}

正如我所说,我没有太多解释分析器输出的经验,但我认为在这个例子中你可以看到程序在 time.sleep 上花费了 2 秒多一点,正如预期的那样,这是由 slow() 调用的。剩下的时间都被join占用了。我认为这就是 Jinja2 处理我的两个 for 循环的方式。

将此示例改编为烧瓶应用程序应该不会太难,只需在模板生成步骤周围添加分析位并将报告写入文件即可。也许您甚至可以从 Web 应用程序中提取模板并在烧瓶之外对其进行分析。

我希望这会有所帮助。

【讨论】:

  • 嗯,我想这和flask-debugtoolbar给出的一样。
【解决方案2】:

对于像正在运行的 Flask 服务器这样的多线程应用程序,我发现通常的 Python 分析工具并不是那么好。

我使用专为多线程应用程序设计的yappi 取得了不错的效果。这很简单:

import yappi
yappi.start()

   [.. do stuff ..]

yappi.stop()
yappi.convert2pstats(yappi.get_func_stats()).dump_stats('myfile.pstats')

这会将配置文件数据保存在pstats 兼容文件中,以便您可以在 python 中交互地检查它:

>>> import pstats 
>>> s = pstats.Stats('myfile.pstats')
>>> s.strip_dirs().sort_stats('cumtime').print_stats()

如果你想聪明一点,你可以将start() 位和stop() 位放在 Flask 处理程序中,这样你就可以点击一个 URL 开始分析,驱动你的应用程序,然后点击另一个 URL 停止分析并编写出统计文件。

【讨论】:

  • 我也试过这个,但我发现这和 flask-debugtoolbar 一样没有帮助(至少在 jinja2 渲染方面)。
猜你喜欢
  • 2011-01-01
  • 2019-03-31
  • 2014-08-04
  • 2022-01-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-17
  • 2015-06-24
相关资源
最近更新 更多