Jinja: Erreur déroutante avec Python 3 et les modèles qui utilisent iteritems()

Créé le 27 sept. 2012  ·  5Commentaires  ·  Source: pallets/jinja

Envisager:

#!/usr/bin/env python3

from collections import OrderedDict

import jinja2

t = '''
{% for key, value in d.iteritems() %}
* {{ key }}: {{ value }}
{% endfor %}
'''

jt = jinja2.Template(t)

d = OrderedDict()
d['one'] = 1
d['two'] = 2
d['three'] = 3

print(jt.render(d=d))

Lorsqu'il est exécuté avec Python 3, vous obtenez une exception déroutante :

Traceback (most recent call last):
  File "jinja2-OrderedDict.py", line 20, in <module>
    print(jt.render(d=d))
  File "/usr/lib/python3/dist-packages/jinja2/environment.py", line 895, in render
    return self.environment.handle_exception(exc_info, True)
  File "/usr/lib/python3/dist-packages/jinja2/environment.py", line 671, in handle_exception
    raise exc_value.with_traceback(tb)
  File "<template>", line 2, in <module>
jinja2.exceptions.UndefinedError: b"'collections.OrderedDict object' has no attribute 'iteritems'"

C'est parce que le modèle utilise des éléments, qui sont supprimés dans Python 3. À partir de l'exception ci-dessus, il n'est pas clair que le problème réside dans le modèle, il devrait l'être.

Cela fonctionne pour les dictionnaires Python 3 normaux car les lignes 205 à 210 de Jinja2 v2.61 rajoutent une méthode iteritems :

    # not available on python 3
    if hasattr(dict, 'iterkeys'):
        iterkeys = _all('iterkeys')
        itervalues = _all('itervalues')
        iteritems = _all('iteritems')
    del _all

Quelle est la meilleure façon de résoudre ce problème ? Mieux détecter les objets de type dict, essayer de cracher une meilleure erreur, etc. ?

Commentaire le plus utile

Les dictionnaires n'ont pas de méthodes iteritem dans 3.x. Vous devrez changer en .items() . Je ne peux rien y faire.

Tous les 5 commentaires

Les dictionnaires n'ont pas de méthodes iteritem dans 3.x. Vous devrez changer en .items() . Je ne peux rien y faire.

Ce serait bien s'il y avait un filtre intégré pour cela et d'autres bizarreries python 2to3.

À moins que vous n'ayez d'énormes dictons, utiliser .items() n'est pas /ça/ mauvais

Voici un moyen de le contourner :

importer six

env = jinja2.Environment(loader=jinja2.FileSystemLoader('your_dir'))
env.globals['six_iteritems'] = six.iteritems
template = env.get_template('your_template')

Ensuite, dans votre modèle :

utilisation:
{% pour la clé, valeur dans six_iteritems (votre var) %}

C'est un peu moche, mais ça marche.

en utilisant .items() à la place .iteritems() a fonctionné

Cette page vous a été utile?
0 / 5 - 0 notes