28 votes

Déboguer Jinja2 dans Google App Engine

Quand je suis en cours d'exécution Jinja2 dans Google App Engine, je reçois inutile des informations de débogage. Je cueille, c'est à cause de cet élément dans la FAQ:

Mon retraçage l'air bizarre. Ce qui se passe?

Si les accélérations module n'est pas compilé et que vous utilisez une installation de Python sans ctypes (Python 2.4 sans ctypes, Jython ou Google AppEngine) Jinja2 est pas en mesure d'assurer l'exactitude des informations de débogage et le traceback est peut-être incomplète. Il n'y a actuellement aucune bonne solution de contournement pour Jython ou l'AppEngine comme ctypes n'est pas disponible et il n'est pas possible d'utiliser les accélérations de l'extension.

Il n'existe pas de "bonne" solution de contournement pour le moment, y a aucune solution de contournement, de sorte que les informations imprimées lorsque des exceptions surviennent peuvent être plus utiles?

Merci pour la lecture.

Brian

29voto

Thomas Johansson Points 650

Vous pouvez contourner ce problème en ajoutant _ctypes et de la gestalt pour le serveur de développement du module C liste blanche avec monkeypatching.

Pour ce faire, placez le fragment de code suivant en haut de votre 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']

Vous pouvez également utiliser cette astuce pour permettre à d'autres modules en C, si vous avez semblable local seul module besoins. Ne noter que ces modules ne fait pas travailler une fois que vous déployez, donc faire preuve de prudence.

Sur SDK 1.6.3 à l'aide de python2.7 vous avez besoin de changer le code ci-dessus à:

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

Sur SDK 1.8.6 pour python 2.7, essayez ceci:

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

2voto

Will McCutchen Points 8193

J'utilise la suite monkeypatch pour permettre légèrement plus d'informations utiles lorsqu'une exception se produit lors de Jinja2 modèle de rendu:

# 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

Cela aura pour résultat un peu plus précis exception retraçage dans vos journaux d'erreur. Je ne pense pas qu'il habituellement, vous montre exactement ce qui s'est passé (mais si je me souviens bien, il le fait parfois), mais il aura au moins étroit à l'exception vers le bas pour le modèle correct.

Pourquoi cela fonctionne, je ne sais pas (ou ne peuvent pas s'en rappeler).

Comme un exemple, j'ai juste ajouté un peu de code qui va déclencher une exception à l'un de mes modèles. Sous le serveur de développement, c'est ce que la "normale" gestionnaire d'exception m'indique:

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

Mais l'exception n'est pas dans l' accounts/base.html modèle, c'est en accounts/edit_card.html. C'est la partie la plus frustrante de débogage Jinja2 modèle d'exception sur App Engine: La source de l'exception est presque toujours déformé. Dans mon expérience, la source est généralement signalé comme un parent, d'un modèle ou comme certains modèles de macro.

À l'exception de journalisation monkeypatch installé, la même exception génère cette de trace dans les logs:

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

Il y a encore beaucoup d'autres informations ici, mais ce traceback au moins des points de moi dans la bonne direction. Il affirme que le problème est à la ligne 54 accounts/edit_card.html (le bon modèle), mais la véritable exception se produit à la ligne 86.

Mais étant donné le bon modèle et la bonne exception, je peux très facilement trouver que le gênants code est-ce

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

où il n'y a pas d' sequence variable dans le modèle de contexte.

Ce n'est pas une solution parfaite, mais je l'ai trouvé puissants utiles.

2voto

Freddie Points 619

Peut-être utilisez-vous simplement le débogueur interactif de PyCharm et parcourez le code:

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

1voto

HoverHell Points 1140

Je ne sais pas si cela sera utile, mais il pourrait être possible d'ajouter au moins un modèle de bloc comme le «débogage» de django qui aidera au moins à localiser le problème.

0voto

Tudorizer Points 2647

Lorsque je rencontre un problème comme celui-ci, j'essaie de le déboguer sur mon shell iPython local. Je me demande quel est le code qui génère un tel bug. Il devrait y avoir un moyen d'écrire un test pour cela.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X