Tech カテゴリのイメージ

ValueError: too many values to unpack (expected 2) の原因と直し方[Python]

タプルやリストを複数の変数に展開しようとしたときに出るのがこのエラーになる。

ValueError: too many values to unpack (expected 2)

逆に右辺が少ない場合はこう出る。

ValueError: not enough values to unpack (expected 2, got 1)

どちらも意味は同じで、左辺に並べた変数の数と、右辺の要素の数が一致していない。

a, b = [1, 2, 3] # 左は2個、右は3個 → too many
a, b, c = [1, 2] # 左は3個、右は2個 → not enough

原因になりやすいパターンを順に見ていく。

1. split の結果が想定の列数でない

CSVやログを分割するときにいちばんよく踏む。

name, age = line.split(",")

データの中に区切り文字が余分に含まれていると、3つ以上に分かれて落ちる。

田中,30 → OK
田中,30,東京 → too many values to unpack

分割数を制限すれば、余分な区切りを含んだまま2つに収められる。

name, age = line.split(",", 1) # 最初の1回だけで分割

残りをまとめて受け取りたいなら、アスタリスクを使う書き方が便利になる。

name, *rest = line.split(",")

restはリストになるので、要素が0個でもエラーにならない。列数が一定でないデータを扱うときの定番になる。

2. 辞書のループで items() を忘れている

辞書をそのまま回すとキーだけが返るので、2つに展開しようとして落ちる。

d = {"a": 1, "b": 2}
for key, value in d: # ValueError
print(key, value)

キーと値の両方が欲しいときはitems()が必要になる。

for key, value in d.items():
print(key, value)

キー名が2文字の文字列だとfor k, v in dが偶然通ってしまい、後で別のデータで落ちるという厄介なこともある。辞書を回すときは常にitems()を意識しておきたい。

3. enumerate と中身の展開を混ぜている

要素自体がタプルの場合、enumerateを付けると入れ子になる。

pairs = [("a", 1), ("b", 2)]
for i, name, value in enumerate(pairs): # ValueError
print(i, name, value)

enumerateが返すのは(0, ("a", 1))という2要素なので、内側もまとめて展開するにはかっこで括る。

for i, (name, value) in enumerate(pairs):
print(i, name, value)

4. 戻り値の個数を勘違いしている

関数やライブラリの戻り値の数が想定と違うパターンになる。

result = cv2.findContours(img, mode, method)
contours, hierarchy = result # バージョンによって3つ返ることがある

このように戻り値の個数がバージョンで変わるものは、末尾から取る書き方にしておくと壊れにくくなる。

contours, hierarchy = cv2.findContours(img, mode, method)[-2:]

自作の関数なら、複数の値を返すよりも辞書やデータクラスで返すほうが、あとから項目が増えても壊れない。

from dataclasses import dataclass
@dataclass
class Result:
name: str
age: int

5. 1行しかないファイルやクエリ結果

データベースやAPIの結果を展開するとき、件数が想定と違うと落ちる。

row1, row2 = cursor.fetchall() # 件数が2でないと落ちる

件数が可変なら展開せず、そのままリストとして扱う。

rows = cursor.fetchall()
for row in rows:
...

要素数がわからないときの調べ方

エラーメッセージには期待した数しか出ないことがあるので、実際の中身を見てしまうのが早い。

parts = line.split(",")
print(len(parts), parts)
name, age = parts

長さと中身を並べて出せば、区切り文字が多いのか、空行なのかがすぐ判別できる。

まとめ

・左辺の変数の数と右辺の要素数が合っていないだけのエラー。多すぎればtoo many、少なすぎればnot enough ・splitmaxsplitを指定するか、name, *rest = ...で余りをまとめて受ける ・辞書のループでキーと値が欲しいときはitems()が必要 ・enumerateで中身もタプルの場合はfor i, (a, b) in enumerate(...)とかっこで括る ・戻り値の個数がバージョンで変わるものは[-2:]のように末尾から取ると壊れにくい ・原因が読めないときはlen()と中身を一緒に出力すれば一発でわかる