28

当我在 Google App Engine 中运行 Jinja2 时,我得到了无用的调试信息。我认为这是因为常见问题解答中的这个项目:

我的追溯看起来很奇怪。发生了什么?

如果加速模块未编译并且您使用的是没有 ctypes 的 Python 安装(没有 ctypes、Jython 或 Google 的 AppEngine 的 Python 2.4)Jinja2 无法提供正确的调试信息,并且回溯可能不完整。目前对于 Jython 或 AppEngine 没有好的解决方法,因为 ctypes 在那里不可用,并且无法使用加速扩展。

虽然目前没有“好的”解决方法,但是否有任何解决方法可以使出现异常时打印的信息更有帮助?

感谢您的阅读。

布赖恩

4

6 回答 6

29

您可以通过使用猴子补丁将 _ctypes 和 gestalt 添加到开发服务器的 C 模块白名单中来解决此问题。

为此,请将以下代码段放在 main.py 的顶部:

import os
if os.environ.get('SERVER_SOFTWARE', '').startswith('Dev'):
    # Enable ctypes for Jinja debugging
    from google.appengine.tools.dev_appserver import HardenedModulesHook
    HardenedModulesHook._WHITE_LIST_C_MODULES += ['_ctypes', 'gestalt']

如果您有类似的仅本地模块需求,您也可以使用此技巧来启用其他 C 模块。请注意,一旦部署,这些模块实际上仍然无法正常工作,因此请谨慎行事。

在使用 python2.7 的 SDK 1.6.3 上,您需要将上述代码更改为:

import os
if os.environ.get('SERVER_SOFTWARE', '').startswith('Dev'):
    # Enable ctypes for Jinja debugging
    import sys
    from google.appengine.tools.dev_appserver import HardenedModulesHook
    assert isinstance(sys.meta_path[0], HardenedModulesHook)
    sys.meta_path[0]._white_list_c_modules += ['_ctypes', 'gestalt']

在适用于 python 2.7 的 SDK 1.8.6 上,试试这个:

PRODUCTION_MODE = not os.environ.get(
    'SERVER_SOFTWARE', 'Development').startswith('Development')
if not PRODUCTION_MODE:
    from google.appengine.tools.devappserver2.python import sandbox
    sandbox._WHITE_LIST_C_MODULES += ['_ctypes', 'gestalt']
于 2010-09-12T10:02:47.157 回答
2

也许只需使用 PyCharm 的交互式调试器并逐步执行代码:

http://www.jetbrains.com/pycharm/quickstart/#RunAndDebug

于 2010-08-05T21:55:08.327 回答
2

当 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在模板上下文中没有变量的地方。

这不是一个完美的解决方案,但我发现它很有帮助。

于 2010-09-16T17:05:23.337 回答
1

A way to avoid monkey-patching (which depends on the changing internals of the SDK) is to use the imp module, which is at least currently not disabled in the local development environment. Then just load _ctypes like this to enable better Jinja2 debugging:

import imp
file, pathname, description =  imp.find_module('_ctypes')
imp.load_module('_ctypes', file, pathname, description)
于 2015-02-02T14:50:42.847 回答
1

不确定这是否会有所帮助,但至少可以添加像 django 的“调试”这样的块模板标签,这至少有助于解决问题。

于 2010-07-23T10:00:47.270 回答
0

当我遇到这样的问题时,我尝试在本地 iPython shell 上对其进行调试。我想知道产生这种错误的代码是什么。应该有一种方法可以为它编写测试。

于 2010-07-25T12:25:40.407 回答