How to Resolve "AttributeError: 'dict' object has no attribute 'iteritems'" in Python
If you're migrating code from Python 2 to Python 3, or running an older script in a modern Python environment, you've likely encountered the error AttributeError: 'dict' object has no attribute 'iteritems'. This is one of the most common Python 2 to Python 3 compatibility issues, and fortunately, it's straightforward to fix.
In this guide, we'll explain why this error happens, show you how to fix it, and cover strategies for making your code compatible with both Python versions if needed.
Why Does This Error Occur?
In Python 2, dictionaries had three methods for accessing key-value pairs:
| Method | Return Type | Description |
|---|---|---|
dict.items() | list of tuples | Returns a full copy as a list |
dict.iteritems() | iterator | Returns a memory-efficient iterator |
dict.viewitems() | view object | Returns a dynamic view of items |
In Python 3, the dictionary API was simplified. The items() method now returns a view object (which is memory-efficient like the old iteritems()), and both iteritems() and viewitems() were completely removed.
When you call iteritems() on a dictionary in Python 3, Python can't find the method and raises:
AttributeError: 'dict' object has no attribute 'iteritems'
The same applies to iterkeys(), itervalues(), viewkeys(), viewitems(), and viewvalues(), all removed in Python 3.
Reproducing the Error
❌ Wrong: Using iteritems() in Python 3:
my_dict = {'a': 1, 'b': 2, 'c': 3}
for key, value in my_dict.iteritems():
print(key, value)
Output:
AttributeError: 'dict' object has no attribute 'iteritems'
How to Fix It
Solution 1: Replace iteritems() with items()
The simplest and most common fix is a direct replacement. In Python 3, items() already returns a lightweight view object, so there's no performance penalty:
my_dict = {'a': 1, 'b': 2, 'c': 3}
for key, value in my_dict.items():
print(key, value)
Output:
a 1
b 2
c 3
This same pattern applies to the other removed methods:
| Python 2 (Removed) | Python 3 (Replacement) |
|---|---|
dict.iteritems() | dict.items() |
dict.iterkeys() | dict.keys() |
dict.itervalues() | dict.values() |
dict.viewitems() | dict.items() |
dict.viewkeys() | dict.keys() |
dict.viewvalues() | dict.values() |
Solution 2: Write Code Compatible with Both Python 2 and Python 3
If you need your code to work across both Python versions (e.g., maintaining a library that supports legacy systems), you can use a compatibility check:
import sys
my_dict = {'a': 1, 'b': 2, 'c': 3}
if sys.version_info[0] >= 3:
items = my_dict.items()
else:
items = my_dict.iteritems()
for key, value in items:
print(key, value)
Output (both Python 2 and 3):
a 1
b 2
c 3
A cleaner approach uses getattr with a fallback: this tries to use iteritems() first (Python 2) and falls back to items() (Python 3) automatically.
my_dict = {'a': 1, 'b': 2, 'c': 3}
items = getattr(my_dict, 'iteritems', my_dict.items)
for key, value in items():
print(key, value)
Output:
a 1
b 2
c 3
Solution 3: Use the six Compatibility Library
The six library provides utilities for writing code that works on both Python 2 and Python 3:
pip install six
import six
my_dict = {'a': 1, 'b': 2, 'c': 3}
for key, value in six.iteritems(my_dict):
print(key, value)
Output:
a 1
b 2
c 3
six also provides six.iterkeys() and six.itervalues() for the corresponding methods.
If you're starting a new project or migrating fully to Python 3, skip six and just use items() directly. The six library is most useful when you must maintain Python 2 compatibility.
Solution 4: Use 2to3 for Automated Migration
If you have a large codebase with many instances of iteritems(), Python's built-in 2to3 tool can automatically convert them:
# Preview the changes without modifying files
2to3 -f dict your_script.py
# Apply the changes in place
2to3 -w -f dict your_script.py
The dict fixer specifically handles the conversion of iteritems(), iterkeys(), itervalues(), and their view* counterparts to the Python 3 equivalents.
Common Scenarios Where This Error Appears
In Dictionary Comprehensions or Transformations
❌ Wrong:
my_dict = {'x': 10, 'y': 20, 'z': 30}
doubled = {k: v * 2 for k, v in my_dict.iteritems()}
Output:
AttributeError: 'dict' object has no attribute 'iteritems'
✅ Correct:
my_dict = {'x': 10, 'y': 20, 'z': 30}
doubled = {k: v * 2 for k, v in my_dict.items()}
print(doubled)
Output:
{'x': 20, 'y': 40, 'z': 60}
In Third-Party Libraries
Sometimes the error comes from a third-party library rather than your own code. In this case:
- Update the library to the latest version:
pip install --upgrade library-name - If no updated version exists, check the library's GitHub issues for patches or forks that support Python 3.
When Passing Dictionary Items to Functions
❌ Wrong:
my_dict = {'name': 'Alice', 'age': 30}
sorted_items = sorted(my_dict.iteritems(), key=lambda x: x[1])
❌ Wrong: Python 3 does not allow comparisons between different types
my_dict = {'name': 'Alice', 'age': 30}
sorted_items = sorted(my_dict.items(), key=lambda x: x[1])
print(sorted_items)
so you get the following Output:
TypeError: '<' not supported between instances of 'int' and 'str'
The sorting problem is a separate issue (mixed data types).
Finding All Occurrences in Your Codebase
Before making changes, find every instance that needs to be updated:
# Search for all deprecated dict methods
grep -rn "\.iteritems\(\)" .
grep -rn "\.iterkeys\(\)" .
grep -rn "\.itervalues\(\)" .
grep -rn "\.viewitems\(\)" .
grep -rn "\.viewkeys\(\)" .
grep -rn "\.viewvalues\(\)" .
In Python 2, items() returned a full list, which consumed more memory for large dictionaries. That's why iteritems() was preferred. In Python 3, items() returns a view object that is already memory-efficient, so there's no reason to look for an iterator alternative. Using items() in Python 3 gives you the best of both worlds.
Conclusion
The AttributeError: 'dict' object has no attribute 'iteritems' error occurs because iteritems() was removed in Python 3. The fix is simple: replace iteritems() with items().
In Python 3, items() already returns a lightweight, memory-efficient view object, so the replacement is a direct one with no performance trade-offs.
If you're maintaining a codebase that must support both Python 2 and 3, use the six library or a getattr fallback. For large-scale migrations, the 2to3 tool can automate the conversion across your entire project.