当 Jinja2 模板渲染期间发生异常时,我使用以下猴子补丁来启用稍微有用的信息:
# Enabling this monkeypatch can help track down hard to find errors that crop
# up during template rendering (since Jinja's own error reporting is so
# unhelpful on AppEngine).
real_handle_exception = environment.handle_exception
def handle_exception(self, *args, **kwargs):
import logging, traceback
logging.error('Template exception:\n%s', traceback.format_exc())
real_handle_exception(self, *args, **kwargs)
environment.handle_exception = handle_exception
这将导致错误日志中的异常回溯更加准确。我认为它通常不会准确地向您显示出了什么问题(但如果我没记错的话,它有时确实如此),但它至少会将异常缩小到正确的模板。
为什么这样有效,我不知道(或不记得)。
例如,我刚刚添加了一些代码,这些代码将触发我的一个模板的异常。在开发服务器下,这是“正常”异常处理程序向我展示的内容:
Traceback (most recent call last):
File "/Users/will/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/ext/webapp/__init__.py", line 511, in __call__
handler.get(*groups)
File "/Users/will/workspace/keypremium/ki/shared/decorators.py", line 27, in inner
return func(self, *args, **kwargs)
File "/Users/will/workspace/keypremium/account/views.py", line 114, in get
self.render_jinja('accounts/edit_card.html', ctx)
File "/Users/will/workspace/keypremium/ki/webapp/handlers.py", line 186, in render_jinja
return self.response.out.write(jinja.render(template_path, new_context))
File "/Users/will/workspace/keypremium/ki/shared/jinja/__init__.py", line 21, in render
return template.render(context)
File "/Users/will/workspace/keypremium/ki/ext/jinja2/environment.py", line 705, in render
return self.environment.handle_exception(exc_info, True)
File "/Users/will/workspace/keypremium/ki/shared/jinja/environment.py", line 24, in handle_exception
real_handle_exception(self, *args, **kwargs)
File "/Users/will/workspace/keypremium/templates/accounts/edit_card.html", line 1, in top-level template code
{% extends 'accounts/base.html' %}
UndefinedError: 'sequence' is undefined
但例外不在accounts/base.html
模板中,它在accounts/edit_card.html
. 这是在 App Engine 上调试 Jinja2 模板异常最令人沮丧的部分:异常的来源几乎总是被歪曲。根据我的经验,源通常报告为父模板或模板宏。
安装了异常日志记录 monkeypatch 后,相同的异常会在日志中生成此回溯:
Traceback (most recent call last):
File "/Users/will/workspace/keypremium/ki/ext/jinja2/environment.py", line 702, in render
return concat(self.root_render_func(self.new_context(vars)))
File "/Users/will/workspace/keypremium/templates/accounts/edit_card.html", line 11, in root
<div class="errors">
File "/Users/will/workspace/keypremium/templates/accounts/base.html", line 11, in root
</html>
File "/Users/will/workspace/keypremium/templates/accounts/edit_card.html", line 54, in block_content
<td>{{ form.cvv2|safe }}</td>
File "/Users/will/workspace/keypremium/ki/ext/jinja2/environment.py", line 352, in getattr
return getattr(obj, attribute)
File "/Users/will/workspace/keypremium/ki/ext/jinja2/runtime.py", line 445, in _fail_with_undefined_error
raise self._undefined_exception(hint)
UndefinedError: 'sequence' is undefined
这里仍然有很多无关的信息,但这个回溯至少为我指明了正确的方向。它声称问题出在accounts/edit_card.html
(正确模板)的第 54 行,但实际异常发生在第 86 行。
但是给定正确的模板和正确的异常,我很容易发现麻烦的代码是这样的
{% for x in sequence.sequence() %}
{{ x.y }}
{% endfor %}
sequence
在模板上下文中没有变量的地方。
这不是一个完美的解决方案,但我发现它很有帮助。