Python ValueErrorの原因と対処法まとめ
PythonのValueErrorは、関数に渡された値が型としては正しいものの、内容が不適切なときに発生するエラーです。文字列から数値への変換失敗やリスト操作など、データを扱う場面で頻繁に遭遇します。この記事ではValueErrorの主な発生パターンと具体的な対処法を解説します。
ValueErrorとは
ValueErrorは「型は合っているが、値が不正」な場合に発生する例外です。TypeErrorが「型そのものが間違っている」エラーであるのに対し、ValueErrorは「型は正しいが値が範囲外・形式不正」であるときに使われます。
エラーメッセージの読み方
number = int("abc")
# ValueError: invalid literal for int() with base 10: 'abc'
このメッセージは「int()に渡された文字列'abc'は10進数として解釈できない不正な値です」という意味です。文字列型を渡すこと自体は正しいのですが、その中身が数値として変換できないためValueErrorになります。
TypeErrorとの違い
# ValueError: 型は正しいが値が不正
int("abc") # 文字列→整数の変換で、変換できない値
# TypeError: 型そのものが間違っている
int([1, 2]) # リスト→整数の変換はそもそも非対応
パターン1: 文字列から数値への変換失敗
最も多いValueErrorのパターンです。
# NG: 数値に変換できない文字列
age = int("二十五")
# ValueError: invalid literal for int() with base 10: '二十五'
price = float("1,000")
# ValueError: could not convert string to float: '1,000'
変換前にバリデーションする
# OK: isdigitで数字のみか確認(整数の場合)
user_input = "25"
if user_input.isdigit():
age = int(user_input)
print(f"年齢: {age}")
else:
print("数値を入力してください")
ただしisdigitは負の数や小数には対応していません。より汎用的にはtry-exceptを使います。
try-exceptで安全に変換する
# OK: try-exceptで変換エラーを捕捉
def safe_int(value, default=0):
try:
return int(value)
except ValueError:
return default
print(safe_int("42")) # 42
print(safe_int("abc")) # 0
print(safe_int("", -1)) # -1
# OK: 小数の変換にも対応
def safe_float(value, default=0.0):
try:
return float(value)
except ValueError:
return default
print(safe_float("3.14")) # 3.14
print(safe_float("abc")) # 0.0
カンマ区切り数値の処理
# NG: カンマ入りの数値文字列
price = int("1,000")
# ValueError
# OK: カンマを除去してから変換
price_str = "1,000"
price = int(price_str.replace(",", ""))
print(price) # 1000
パターン2: リスト操作でのValueError
リストのremoveメソッドやindexメソッドで、存在しない要素を指定するとValueErrorが発生します。
# NG: リストに存在しない要素を削除
fruits = ["りんご", "みかん", "ぶどう"]
fruits.remove("バナナ")
# ValueError: list.remove(x): x not in list
# NG: リストに存在しない要素のインデックスを取得
fruits = ["りんご", "みかん", "ぶどう"]
idx = fruits.index("バナナ")
# ValueError: 'バナナ' is not in list
事前チェックしてから操作する
# OK: in演算子で存在確認してからremove
fruits = ["りんご", "みかん", "ぶどう"]
target = "バナナ"
if target in fruits:
fruits.remove(target)
else:
print(f"{target}はリストに含まれていません")
try-exceptで処理する
# OK: try-exceptで安全に処理
fruits = ["りんご", "みかん", "ぶどう"]
try:
idx = fruits.index("バナナ")
print(f"インデックス: {idx}")
except ValueError:
print("バナナはリストに含まれていません")
パターン3: アンパック時のValueError
タプルやリストのアンパック(分解代入)で、要素数と変数の数が合わないとValueErrorが発生します。
# NG: 要素数と変数の数が合わない
data = (1, 2, 3)
a, b = data
# ValueError: too many values to unpack (expected 2)
data = (1, 2)
a, b, c = data
# ValueError: not enough values to unpack (expected 3, got 2)
アスタリスクを使って可変長に対応する
# OK: *で残りをまとめて受け取る
data = (1, 2, 3, 4, 5)
first, second, *rest = data
print(first) # 1
print(second) # 2
print(rest) # [3, 4, 5]
# 先頭と末尾だけ取得
first, *middle, last = data
print(first) # 1
print(last) # 5
print(middle) # [2, 3, 4]
要素数を確認してからアンパックする
# OK: 要素数を事前チェック
data = (1, 2, 3)
if len(data) == 2:
a, b = data
elif len(data) == 3:
a, b, c = data
else:
print(f"予期しない要素数: {len(data)}")
パターン4: 日付・時刻の変換でのValueError
日付文字列のフォーマットが合わないとValueErrorが発生します。
from datetime import datetime
# NG: フォーマットが一致しない
date = datetime.strptime("2026/04/01", "%Y-%m-%d")
# ValueError: time data '2026/04/01' does not match format '%Y-%m-%d'
# OK: フォーマットを合わせる
date = datetime.strptime("2026/04/01", "%Y/%m/%d")
print(date) # 2026-04-01 00:00:00
# NG: 存在しない日付
date = datetime.strptime("2026-02-30", "%Y-%m-%d")
# ValueError: day is out of range for month
日付変換を安全に行う
from datetime import datetime
def parse_date(date_str, fmt="%Y-%m-%d"):
try:
return datetime.strptime(date_str, fmt)
except ValueError as e:
print(f"日付の変換に失敗しました: {e}")
return None
result = parse_date("2026-04-01")
print(result) # 2026-04-01 00:00:00
result = parse_date("2026-02-30")
# 日付の変換に失敗しました: day is out of range for month
print(result) # None
複数のフォーマットに対応する
from datetime import datetime
def parse_date_flexible(date_str):
formats = ["%Y-%m-%d", "%Y/%m/%d", "%d/%m/%Y", "%Y年%m月%d日"]
for fmt in formats:
try:
return datetime.strptime(date_str, fmt)
except ValueError:
continue
print(f"対応するフォーマットが見つかりません: {date_str}")
return None
print(parse_date_flexible("2026-04-01")) # 2026-04-01 00:00:00
print(parse_date_flexible("2026/04/01")) # 2026-04-01 00:00:00
print(parse_date_flexible("2026年04月01日")) # 2026-04-01 00:00:00
パターン5: 数学関数でのValueError
数学関数に定義域外の値を渡すとValueErrorが発生します。
import math
# NG: 負の数の平方根
result = math.sqrt(-1)
# ValueError: math domain error
# NG: 0以下の対数
result = math.log(0)
# ValueError: math domain error
値の範囲をチェックしてから計算する
import math
def safe_sqrt(value):
if value < 0:
print(f"負の数の平方根は計算できません: {value}")
return None
return math.sqrt(value)
print(safe_sqrt(16)) # 4.0
print(safe_sqrt(-1)) # None(エラーメッセージ表示)
複素数で処理する場合
import cmath
# cmathモジュールなら負の数の平方根も計算可能
result = cmath.sqrt(-1)
print(result) # 1j(虚数単位)
ユーザー入力のバリデーション
ValueErrorの多くはユーザー入力に起因します。入力値を受け取る段階でバリデーションを行うことが重要です。
input関数での入力受付
# NG: バリデーションなし
age = int(input("年齢を入力してください: "))
# 数値以外を入力するとValueError
# OK: ループでバリデーション
while True:
user_input = input("年齢を入力してください: ")
try:
age = int(user_input)
if 0 <= age <= 150:
break
else:
print("0から150の範囲で入力してください")
except ValueError:
print("数値を入力してください")
print(f"年齢: {age}")
範囲チェック付きの変換関数
def get_int_in_range(value, min_val, max_val, name="値"):
try:
result = int(value)
except ValueError:
raise ValueError(f"{name}は整数で指定してください: {value}")
if not (min_val <= result <= max_val):
raise ValueError(
f"{name}は{min_val}から{max_val}の範囲で指定してください: {result}"
)
return result
# 使用例
try:
score = get_int_in_range("85", 0, 100, "点数")
print(f"点数: {score}") # 点数: 85
except ValueError as e:
print(e)
まとめ
ValueErrorは「型は正しいが値が不正」なときに発生するエラーです。主な対処法を整理します。
- 文字列から数値への変換はtry-exceptで囲み、変換失敗に備える
- リストの
removeやindexは要素の存在を事前に確認する - アンパックでは要素数と変数の数を合わせるか、アスタリスクで可変長にする
- 日付変換ではフォーマット文字列と入力文字列の形式を一致させる
- ユーザー入力は受け取った段階でバリデーションを行う
ValueErrorを防ぐ基本は「変換や操作の前に値が妥当かチェックすること」です。特に外部からの入力データは常にバリデーションを行う習慣をつけましょう。