How to Migrate Dictionary Python2 items() to Python3 items()
When migrating from Python 2 to Python 3, iteritems() removal is among the most common causes of breakage. Understanding the difference helps you update legacy code correctly.
The Python 3 Standard
In Python 3, iteritems() no longer exists. The items() method now returns a view object that's memory-efficient and dynamic: combining the best of both Python 2 methods.
data = {"a": 1, "b": 2, "c": 3}
# Returns a dict_items view object
items_view = data.items()
print(type(items_view))
# Iterate efficiently
for key, value in data.items():
print(f"{key}: {value}")
Output:
<class 'dict_items'>
a: 1
b: 2
c: 3
View objects reflect dictionary changes in real-time:
data = {"x": 10}
view = data.items()
print(list(view))
data["y"] = 20
print(list(view))
Output:
[('x', 10)]
[('x', 10), ('y', 20)]
The Python 2 Legacy Behavior
Python 2 offered two distinct methods with different memory characteristics:
# Python 2 only - DO NOT USE in Python 3
data = {"a": 1, "b": 2}
# items() created a full list copy in memory
pairs_list = data.items() # [('a', 1), ('b', 2)]
# iteritems() returned a memory-efficient iterator
pairs_iter = data.iteritems() # <dictionary-itemiterator>
For large dictionaries, items() in Python 2 consumed significant memory since it built an entire list of tuples.
Migrating Your Code
Replace all occurrences of iteritems() with items():
# ❌ Python 2 code (breaks in Python 3)
for key, value in config.iteritems():
process(key, value)
# ✅ Python 3 equivalent
for key, value in config.items():
process(key, value)
Example with actual code:
# Python 3
config = {"host": "localhost", "port": 8080, "debug": True}
for key, value in config.items():
print(f"{key} = {value}")
Output:
host = localhost
port = 8080
debug = True
The same applies to keys() and values():
# ❌ Python 2
for k in my_dict.iterkeys():
pass
for v in my_dict.itervalues():
pass
# ✅ Python 3
for k in my_dict.keys():
pass
for v in my_dict.values():
pass
Example:
data = {"x": 100, "y": 200, "z": 300}
print("Keys:", list(data.keys()))
print("Values:", list(data.values()))
Output:
Keys: ['x', 'y', 'z']
Values: [100, 200, 300]
If you need an actual list rather than a view (for indexing or multiple independent iterations), wrap the view explicitly:
items_list = list(data.items())
first_pair = items_list[0]
Example:
data = {"a": 1, "b": 2, "c": 3}
items_list = list(data.items())
print(items_list[0])
print(items_list[1])
print(len(items_list))
Output:
('a', 1)
('b', 2)
3
Writing Compatible Code
For codebases that must support both Python versions during transition, use a compatibility approach:
import sys
if sys.version_info[0] >= 3:
iteritems = lambda d: d.items()
else:
iteritems = lambda d: d.iteritems()
# Use throughout your code
for key, value in iteritems(my_dict):
process(key, value)
Or use the six compatibility library:
import six
for key, value in six.iteritems(my_dict):
process(key, value)
Example with six:
import six
data = {"name": "Alice", "age": 30, "city": "NYC"}
for key, value in six.iteritems(data):
print(f"{key}: {value}")
Output (Python 3):
name: Alice
age: 30
city: NYC
Unless you're maintaining legacy systems, focus solely on Python 3. Python 2 reached end-of-life in January 2020.
Method Comparison
| Method | Python 2 Behavior | Python 3 Behavior |
|---|---|---|
items() | Returns list (heavy memory) | Returns view (lightweight) |
iteritems() | Returns iterator (lightweight) | ❌ Removed |
keys() | Returns list | Returns view |
iterkeys() | Returns iterator | ❌ Removed |
values() | Returns list | Returns view |
itervalues() | Returns iterator | ❌ Removed |
Summary
Forget iteritems() entirely for modern Python development. In Python 3, items() provides memory-efficient view objects that serve the same purpose. Simply replace iteritems() with items() during migration: no other changes needed.