Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Confusing error w/ Python 3 and templates that use iteritems() #150

Closed
samatjain opened this issue Sep 26, 2012 · 5 comments
Closed

Confusing error w/ Python 3 and templates that use iteritems() #150

samatjain opened this issue Sep 26, 2012 · 5 comments

Comments

@samatjain
Copy link

Consider:

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

When run w/ Python 3, you get an confusing exception:

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

This is because the template uses iteritems, which is removed in Python 3. From the above exception, it's not clear the problem is in the template—it should be.

It works for normal Python 3 dictionaries because lines 205–210 of Jinja2 v2.61 add back an iteritems method:

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

What's the best way to fix this? Better detect dict-like objects, try to spit out a better error, etc?

@mitsuhiko
Copy link
Contributor

Dictionaries do not have iteritem methods in 3.x. You will need to change to .items(). Nothing I can do about that.

@wryfi
Copy link

wryfi commented Mar 20, 2017

It would be nice if there were a built-in filter for this and other python 2to3 oddities.

@ThiefMaster
Copy link
Member

Unless you have huge dicts, using .items() is not /that/ bad

@bkruger99
Copy link

Here's a way to get around it:

import six

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

Then in your template:

use:
{% for key, value in six_iteritems(your var) %}

It's kinda ugly, but it does work.

@catdkny
Copy link

catdkny commented Sep 28, 2017

using .items() instead .iteritems() worked

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Nov 13, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants