Отладка Jinja2 в Google App Engine - PullRequest
28 голосов
/ 21 июня 2010

Когда я запускаю Jinja2 в Google App Engine, я получаю бесполезную информацию об отладке.Я понимаю, что это из-за этого пункта в FAQ:

Мои трассировки выглядят странно.Что происходит?

Если модуль ускорений не скомпилирован, и вы используете установку Python без ctypes (Python 2.4 без ctypes, Jython или Google AppEngine) Jinja2 не может предоставить правильную информацию об отладке и трассировкуможет быть неполным.В настоящее время нет хорошего обходного пути для Jython или AppEngine, так как ctypes там недоступен, и невозможно использовать расширение speedups.

Хотя для этого пока нет «хорошего» обходного пути,есть любой обходной путь, чтобы информация, напечатанная при возникновении исключений, могла быть более полезной?

Спасибо за чтение.

Брайан

Ответы [ 6 ]

29 голосов
/ 12 сентября 2010

Вы можете обойти это, добавив _ctypes и gestalt в белый список модуля C сервера разработки с помощью monkeypatching.

Для этого поместите следующий фрагмент вверху вашего 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, если у вас есть аналогичные локальные потребности модуля.Обратите внимание, что эти модули на самом деле не будут работать после развертывания, поэтому действуйте осторожно.

В SDK 1.6.3 с использованием python2.7 вам нужно изменить приведенный выше код на:

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']

В SDK 1.8.6 для Python 2.7 попробуйте следующее:

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']
2 голосов
/ 16 сентября 2010

Я использую следующий monkeypatch для включения чуть более полезной информации, когда возникает исключение во время рендеринга шаблона 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. Это самая неприятная часть отладки исключений шаблонов Jinja2 в App Engine: источник исключения почти всегда искажается. По моему опыту, источник обычно сообщается либо как родительский шаблон, либо как некоторый макрос шаблона.

При установленном 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

Здесь все еще много посторонней информации, но эта обратная связь, по крайней мере, указывает мне верное направление. Он утверждает, что проблема в строке 54 accounts/edit_card.html (правильный шаблон), но фактическое исключение происходит в строке 86.

Но, учитывая правильный шаблон и правильное исключение, я довольно легко могу обнаружить, что проблемный код - это

{% for x in sequence.sequence() %}
    {{ x.y }}
{% endfor %}

, где в контексте шаблона нет переменной sequence.

Это не идеальное решение, но я нашел его очень полезным.

2 голосов
/ 06 августа 2010

Возможно, просто используйте интерактивный отладчик PyCharm и выполните код:

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

1 голос
/ 02 февраля 2015

Одним из способов избежать внесения изменений (который зависит от изменений внутренних компонентов SDK) является использование модуля imp, который по крайней мере в настоящее время не отключен в локальной среде разработки.Затем просто загрузите _ctypes, чтобы улучшить отладку Jinja2:

import imp
file, pathname, description =  imp.find_module('_ctypes')
imp.load_module('_ctypes', file, pathname, description)
1 голос
/ 23 июля 2010

Не уверен, будет ли это полезно, но, возможно, будет возможно, по крайней мере, добавить блочный шаблон тега, такой как 'debug' django, который по крайней мере поможет локализовать проблему.

0 голосов
/ 25 июля 2010

Когда я сталкиваюсь с такой проблемой, я пытаюсь отладить ее в своей локальной оболочке iPython.Интересно, что за код генерирует такую ​​ошибку.Должен быть способ написать тест для него.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...