Python ValueError: too many values to unpack (expected 2) の修正方法

beginner🐍 Python2026-03-18| Python 3.x(全プラットフォーム: Linux, macOS, Windows)

Error Message

ValueError: too many values to unpack (expected 2)
#python#tuple#unpacking#list#value-error

TL;DR

イテラブルの値の数が、代入の左辺の変数の数より多い場合に発生します。変数を追加して数を合わせるか、*restを使って余分な値を吸収するか、アンパック対象を修正してください。

# エラーになるコード
a, b = (1, 2, 3)  # ValueError: too many values to unpack (expected 2)

# 修正済み — 数を合わせる
a, b, c = (1, 2, 3)

# 修正済み — スターで余分な値を収集
a, b, *rest = (1, 2, 3, 4, 5)  # rest = [3, 4, 5]

根本原因

Pythonのアンパックは位置指定です。左辺の変数の数は、右辺の値の数と正確に一致する必要があります。値が1つ多いだけで ValueError: too many values to unpack (expected N) が発生します。

最も多く発生する4つの状況:

  • タプルやリストを、それが含む値より少ない変数に代入する
  • .items()なしで辞書をイテレートする — 各キーが文字のイテラブルとして扱われる
  • 想定外のフィールドが含まれるCSV行やAPIレスポンスをアンパックする
  • 各要素が3つ以上のアイテムを持つ場合に for a, b in some_list を使用する

修正1 — 変数の数を合わせる

値の数を数えて、正しい数の変数を宣言します。リテラルの場合は明らかですが、自分で書いたものではなく関数呼び出しからデータが来る場合は見落としやすいです。

# エラーになるコード
first, last = "John", "Paul", "George", "Ringo"

# 正しいコード
first, second, third, fourth = "John", "Paul", "George", "Ringo"

常に正確な数が事前にわかっている固定構造に適しています。

修正2 — スター(*) 構文を使って全て受け取る

特定の位置だけが必要な場合は、* で残りをリストに吸収させます:

# 最初と最後を取得し、中間を収集
first, *middle, last = [10, 20, 30, 40, 50]
print(first)   # 10
print(last)    # 50
print(middle)  # [20, 30, 40]

# 最初の2つを取得し、残りを破棄
a, b, *_ = get_csv_row()  # _ は破棄の慣例

スター構文は可変長データをきれいに処理します — CSV行、APIペイロード、予告なく余分なフィールドが現れる可能性がある全てのデータに対応します。*_ パターンは「もっとあることはわかっているが、必要ない」というPythonの慣用的な表現です。

修正3 — .items()なしの辞書イテレーション

多くの人がはまるケースです。.items()なしで辞書をイテレートすると、(key, value)ペアではなくキーが得られます。キーが"name"のような文字列の場合、Pythonは4つの個別文字として認識し、2つの変数へのアンパックは即座に失敗します:

# エラーになるコード — (key, value)ペアではなくキーをイテレートする
data = {"name": "Alice", "age": 30}
for key, value in data:  # ValueError: "name" は4文字で2文字ではない
    print(key, value)

# 修正済み
for key, value in data.items():
    print(key, value)
# name Alice
# age 30

キーと値のペアには .items()、キーだけには .keys()、値だけには .values() を使用します。

修正4 — ループ内でのアンパック

リストの各要素には3つのフィールドがありますが、2つしかアンパックしていません。Pythonはどのフィールドを省略するかを推測できません:

# データは1行に3フィールド
records = [
    ("alice", "alice@example.com", "admin"),
    ("bob",   "bob@example.com",   "user"),
]

# エラーになるコード — 3つの値に対して2つの変数しかない
for name, email in records:  # ValueError
    print(name, email)

# 修正済み — 3つ目の変数を追加
for name, email, role in records:
    print(name, email, role)

# 修正済み — roleが不要な場合はスターを使用
for name, email, *_ in records:
    print(name, email)

修正5 — 関数の戻り値のアンパック

戻り値は変化します。かつて2つの値を返していた関数に、後からタイムスタンプ、ステータスコード、リフレッシュレートなど3つ目のフィールドが追加されることがあります。ちょうど2つの変数にアンパックしている全ての呼び出し元は、実行時まで気づかずに壊れてしまいます:

def get_dimensions():
    return 1920, 1080, 144  # リフレッシュレートは後から追加

# エラーになるコード
width, height = get_dimensions()  # ValueError

# 修正済み
width, height, refresh = get_dimensions()

# 余分な値が本当に不要な場合
width, height, *_ = get_dimensions()

その関数を管理している場合、戻り値の追加は破壊的変更として扱います。ドキュメント化してください。呼び出し元は知る必要があります。

修正6 — CSVファイルの解析

CSVファイルは特にこの問題が起きやすいです。末尾のカンマ、オプションフィールド、スキーマの変更 — これら全てが予想より多くのカラムを持つ行を生成します:

import csv

# 行が2列以上ある場合にエラーになるコード
with open("data.csv") as f:
    reader = csv.reader(f)
    for row in reader:
        name, score = row  # 余分なカラムがある行でValueError

# 修正済み — 代わりに行のインデックスを使用
with open("data.csv") as f:
    reader = csv.reader(f)
    for row in reader:
        name = row[0]
        score = row[1]

# より良い方法 — 名前付きカラムにはDictReaderを使用
with open("data.csv") as f:
    reader = csv.DictReader(f)
    for row in reader:
        print(row["name"], row["score"])

修正が機能したことを確認する方法

次の実行でValueErrorが発生しなければ、それが確認です。API、ファイル、データベースなどの外部データソースの場合、アンパックロジックを書く前に生のサンプルを出力してください:

# アンパックを決める前に形状を確認
data = some_function()
print(type(data), len(data), data)

# 確認後、自信を持ってアンパック
a, b, c = data

最初のprint文1つで、後の10分のデバッグを節約できます。

クイック診断チェックリスト

  • 値と変数の数を数える — 一致する必要があります。または *rest を使用
  • 辞書をイテレートしている? キーと値のペアを取得するために .items() を追加
  • ループアンパック for a, b in list? まず各要素の実際の長さを確認
  • CSVやJSONを解析している? カラムが変更された可能性があります — アンパック前に生の行を出力
  • タプルを返す関数を呼び出している? 戻り値の数が増えていないか確認

Related Error Notes