Jinja: Erro confuso com Python 3 e modelos que usam iteritems ()

Criado em 27 set. 2012  ·  5Comentários  ·  Fonte: pallets/jinja

Considerar:

#!/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))

Quando executado com Python 3, você obtém uma exceção confusa:

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

Isso ocorre porque o modelo usa iteritens, que são removidos do Python 3. A partir da exceção acima, não está claro se o problema está no modelo - deveria estar.

Funciona para dicionários normais do Python 3 porque as linhas 205–210 do Jinja2 v2.61 adicionam de volta um método de iteritens:

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

Qual é a melhor maneira de consertar isso? Detectar melhor objetos do tipo dict, tentar cuspir um erro melhor, etc?

Comentários muito úteis

Os dicionários não têm métodos iteritem no 3.x. Você precisará mudar para .items() . Nada que eu possa fazer sobre isso.

Todos 5 comentários

Os dicionários não têm métodos iteritem no 3.x. Você precisará mudar para .items() . Nada que eu possa fazer sobre isso.

Seria bom se houvesse um filtro embutido para esta e outras esquisitices do python 2to3.

A menos que você tenha grandes dictos, usar .items() não é / tão / ruim

Esta é uma maneira de contornar isso:

importar seis

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

Então, em seu modelo:

usar:
{% para chave, valor em six_iteritems (sua var)%}

É meio feio, mas funciona.

usando .items () em vez de .iteritems () funcionou

Esta página foi útil?
0 / 5 - 0 avaliações