You upgraded pandas — or cloned a project that uses a newer version — and now existing code raises:
AttributeError: 'DataFrame' object has no attribute 'iteritems'
Or on a Series:
AttributeError: 'Series' object has no attribute 'iteritems'
This error means you are running pandas 2.0 or later against code written for pandas 1.x. The .iteritems() method was deprecated in pandas 1.5 (August 2022) and completely removed in pandas 2.0 (April 2023). The fix is a one-character change, but the same pandas 2.0 release removed several other APIs that may be lurking in the same codebase.
pandas 2.0 was released in April 2023 and is the first major version with breaking API removals that had been deprecated for years. The full traceback when calling .iteritems() looks like this:
Traceback (most recent call last):
File "process_data.py", line 14, in <module>
for col_name, col_data in df.iteritems():
File "/usr/local/lib/python3.11/site-packages/pandas/core/generic.py", line 6299, in __getattr__
return object.__getattribute__(self, name)
AttributeError: 'DataFrame' object has no attribute 'iteritems'. Did you mean: 'itertuples'?
The "Did you mean: 'itertuples'?" suggestion is not the right fix — itertuples() iterates over rows, not columns. The correct replacement is .items().
import pandas as pd
# Check your pandas version
print(pd.__version__)
# 2.x.x → iteritems() is gone
# 1.5.x → iteritems() still works but shows FutureWarning
# 1.4.x → iteritems() works silently
# Reproduce the error (pandas >= 2.0)
df = pd.DataFrame({
'temperature': [22.1, 19.8, 25.3],
'humidity': [0.55, 0.72, 0.41],
'pressure': [1013, 1009, 1017]
})
# This raises AttributeError on pandas >= 2.0
for col_name, col_data in df.iteritems():
print(col_name, col_data.mean())
.items() is the direct replacement for .iteritems() on both DataFrame and Series. It has the identical signature, return type, and behavior. The only difference is the name.
import pandas as pd
df = pd.DataFrame({
'temperature': [22.1, 19.8, 25.3],
'humidity': [0.55, 0.72, 0.41],
'pressure': [1013, 1009, 1017]
})
# Before (pandas 1.x) — raises AttributeError on pandas 2.0+
# for col_name, col_data in df.iteritems():
# print(col_name, col_data.mean())
# After (works on all pandas versions including 2.0+)
for col_name, col_data in df.items():
print(f"{col_name}: mean={col_data.mean():.2f}")
# Output:
# temperature: mean=22.40
# humidity: mean=0.56
# pressure: mean=1013.00
import pandas as pd
s = pd.Series({'a': 10, 'b': 20, 'c': 30})
# Before (pandas 1.x)
# for idx, val in s.iteritems():
# print(idx, val)
# After (pandas 2.0+)
for idx, val in s.items():
print(idx, val)
# a 10
# b 20
# c 30
The items() method on a DataFrame yields (column_name, Series) pairs — the same as before. The items() method on a Series yields (index_label, value) pairs — also the same as before. This is a pure rename with no behavioral change.
# Quick audit from Python to find all occurrences before changing them
import subprocess
result = subprocess.run(
['grep', '-rn', r'\.iteritems()', '.', '--include=*.py'],
capture_output=True, text=True
)
print(result.stdout)
# ./analysis/process_data.py:14: for col_name, col_data in df.iteritems():
# ./utils/helpers.py:87: for k, v in series.iteritems():
# Bash one-liner to replace across all Python files in the project
find . -name "*.py" -exec sed -i 's/\.iteritems()/.items()/g' {} +
# Verify no occurrences remain
grep -rn '\.iteritems()' . --include='*.py'
The replacement is safe to do blindly — .items() was available on DataFrame and Series since pandas 0.24 (2019), so the renamed version works on all supported versions.
If you are migrating a codebase from pandas 1.x to 2.x, iteritems() is usually not the only thing that breaks. These APIs were also removed in pandas 2.0:
import pandas as pd
df1 = pd.DataFrame({'a': [1, 2], 'b': [3, 4]})
df2 = pd.DataFrame({'a': [5, 6], 'b': [7, 8]})
# Before (pandas 1.x) — AttributeError on pandas 2.0+
# combined = df1.append(df2, ignore_index=True)
# After
combined = pd.concat([df1, df2], ignore_index=True)
print(combined)
# a b
# 0 1 3
# 1 2 4
# 2 5 7
# 3 6 8
import pandas as pd
s = pd.Series([True, False, True])
# Before (pandas 1.x, ambiguous but worked for length-1 Series)
# if bool(s): # raises ValueError in pandas 2.0 for len > 1
# The correct way — always was, now enforced
if s.any():
print("At least one True")
if s.all():
print("All True")
# For a single-element comparison result:
value = pd.Series([42])
if (value > 10).item(): # .item() extracts the scalar
print("Greater than 10")
import pandas as pd
df = pd.DataFrame({'category': ['A', 'B', 'A'], 'value': [10, 20, 30]})
# Before (pandas 1.x) — chained indexing, raised SettingWithCopyWarning
# df[df['category'] == 'A']['value'] = 99 # often silently failed
# After — pandas 2.0 enforces Copy-on-Write (CoW), this no longer modifies df
# Use .loc[] instead:
df.loc[df['category'] == 'A', 'value'] = 99
print(df)
# category value
# 0 A 99
# 1 B 20
# 2 A 99
import pandas as pd
df = pd.DataFrame({'a': [1, 2, 3], 'b': ['x', 'y', 'z'], 'c': [4.0, 5.0, 6.0]})
# Before (pandas 1.x) — silently skipped non-numeric columns
# df.mean() # returned mean of 'a' and 'c' only
# After (pandas 2.0) — must specify numeric_only explicitly
print(df.mean(numeric_only=True))
# a 2.0
# c 5.0
# dtype: float64
import pandas as pd
# Runtime version
print(pd.__version__)
# Check against a version floor
from packaging.version import Version
if Version(pd.__version__) < Version("2.0.0"):
print("Running pandas 1.x — iteritems() available")
else:
print("Running pandas 2.x — use .items() instead")
# Check what version is installed
pip show pandas
# Pin a safe version if you cannot upgrade all code yet
pip install "pandas>=1.5,<2.0"
# Or upgrade to 2.x and fix the code
pip install --upgrade pandas
If you maintain a library or package, add a pandas version floor to your requirements.txt or pyproject.toml so users get a clear error at install time rather than a runtime AttributeError:
# requirements.txt
pandas>=2.0.0
# pyproject.toml
[project]
dependencies = [
"pandas>=2.0.0",
]
If you had been running pandas 1.5.x, every call to .iteritems() would have shown:
FutureWarning: DataFrame.iteritems is deprecated. Use DataFrame.items instead.
pandas 1.5 was released in August 2022, giving eight months of warning before the 2.0 removal. The lesson for any production codebase: run your test suite against the current version with deprecation warnings enabled and treat FutureWarning from major library dependencies as technical debt to clear before the next major version ships.
import warnings
import pandas as pd
# Treat FutureWarnings from pandas as errors during development
# so they surface in CI before they become AttributeErrors
warnings.filterwarnings("error", category=FutureWarning, module="pandas")
df = pd.DataFrame({'a': [1, 2, 3]})
# On pandas 1.5.x this now raises FutureWarning as an error,
# forcing you to fix it before upgrading to 2.0
for col, data in df.iteritems(): # raises FutureWarning -> treated as error
print(col, data.mean())
Add this warnings.filterwarnings call to your test configuration (e.g., conftest.py in pytest) so deprecation warnings from any library surface during CI before they become production errors.
.iteritems() after deprecating it in pandas 1.5..iteritems() with .items() everywhere — same signature, same return type.DataFrame.append() → pd.concat(); bool(Series) → .any()/.all(); chained assignment silently fails under CoW.FutureWarning as errors in CI so the next deprecation wave surfaces before it breaks production.