7. エラーと向き合う
前回は関数について学びました。今回は、プログラミングで避けられない「エラー」との付き合い方を学んでいきましょう。
7.1 エラーとは?よくあるミスとその原因
エラーは「プログラムが上手く動かないとき」に発生するメッセージです:
よくあるエラーの例
# よくあるエラーの例
# 1. NameError: 存在しない変数を使おうとした
print(undefined_variable) # 定義していない変数を使用
# 2. TypeError: 異なる型の演算
text = "123"
result = text + 456 # 文字列と数値の足し算
# 3. IndexError: リストの範囲外にアクセス
numbers = [1, 2, 3]
print(numbers[5]) # 存在しない位置を指定
# 4. ZeroDivisionError: 0での割り算
result = 10 / 0 # ゼロ除算
# 5. ValueError: 不適切な値の変換
number = int("abc") # 数値に変換できない文字列
よくあるエラーの原因と対策
- 変数名のタイプミス → スペルチェック
- カッコの対応忘れ → エディタの補完機能を使う
- インデントのズレ → 視覚的に確認する
- データ型の誤り → 型変換を適切に行う
7.2 try-except でエラーに負けないプログラム作り
try-exceptを使うと、エラーが発生しても処理を続行できます:
基本的なtry-except
# 基本的なtry-except
try:
# エラーが発生するかもしれない処理
number = int(input("数字を入力してください:"))
print(f"入力された数字は{number}です")
except ValueError:
# エラーが発生したときの処理
print("数字以外が入力されました")
# 複数のエラーを扱う
def divide_numbers():
try:
num1 = int(input("1つ目の数字:"))
num2 = int(input("2つ目の数字:"))
result = num1 / num2
print(f"結果:{result}")
except ValueError:
print("数字を入力してください")
except ZeroDivisionError:
print("0で割ることはできません")
except: # その他のすべてのエラー
print("予期せぬエラーが発生しました")
7.3 エラーメッセージを読んで問題箇所を特定する
エラーメッセージには重要な情報が含まれています:
エラーメッセージの例
"""
TypeError: can only concatenate str (not "int") to str
at line 15 in file "example.py"
text = "答え:" + 42
このエラーメッセージから分かること:
1. エラーの種類:TypeError(型の不一致)
2. 発生場所:15行目
3. 原因:文字列と整数の連結
"""
# 修正例
text = "答え:" + str(42) # 整数を文字列に変換してから連結
# エラーメッセージの主な要素
"""
1. エラーの種類(TypeError, ValueError など)
2. エラーの説明文
3. エラーが発生したファイル名と行番号
4. 問題のあるコードの部分
"""
7.4 print デバッグでコードを細かくチェック
print文を使って、プログラムの動きを確認できます:
printデバッグの例
def calculate_total(items):
total = 0
print(f"計算開始:items = {items}") # デバッグ用出力
for item in items:
print(f"処理中:item = {item}") # 各ステップの確認
total += item
print(f"現在の合計:{total}") # 中間結果の確認
print(f"計算終了:total = {total}") # 最終結果の確認
return total
# プログラムの実行
numbers = [10, 20, 30]
result = calculate_total(numbers)
"""
出力例:
計算開始:items = [10, 20, 30]
処理中:item = 10
現在の合計:10
処理中:item = 20
現在の合計:30
処理中:item = 30
現在の合計:60
計算終了:total = 60
"""
7.5 コメントや整形でバグを減らす工夫
コードを整理することで、バグを防ぐことができます:
コメントや整形でバグを減らす工夫
# 悪い例
def calc(x,y,z):
a=x+y
if a>10:b=a*z
else:b=a/z
return b
# 良い例
def calculate_result(base_num, add_num, multiplier):
"""
2つの数の和を計算し、条件に応じて乗算または除算を行う
Args:
base_num: 基準となる数
add_num: 加算する数
multiplier: 乗除算に使う数
Returns:
計算結果
"""
# 最初の2つの数を加算
sum_result = base_num + add_num
# 合計が10より大きければ乗算、それ以外は除算
if sum_result > 10:
final_result = sum_result * multiplier
else:
final_result = sum_result / multiplier
return final_result
7.6 あえてエラーを起こして練習する
エラーを理解するために、意図的にエラーを発生させてみましょう:
あえてエラーを起こして練習する
def practice_errors():
# 1. NameError
try:
print(undefined_name)
except NameError as e:
print(f"変数が定義されていません:{e}")
# 2. TypeError
try:
result = "hello" + 123
except TypeError as e:
print(f"型が合っていません:{e}")
# 3. IndexError
try:
list_data = [1, 2, 3]
print(list_data[10])
except IndexError as e:
print(f"リストの範囲外です:{e}")
# 各種エラーを体験
practice_errors()
7.7 テスト用のチェックを追加する
テストコードを書いて、プログラムの動作を確認できます:
テスト用のチェックを追加する
def test_calculation_functions():
"""計算関数のテスト"""
# 足し算のテスト
assert add(2, 3) == 5, "2 + 3 は 5 になるはず"
assert add(-1, 1) == 0, "-1 + 1 は 0 になるはず"
# 掛け算のテスト
assert multiply(2, 3) == 6, "2 * 3 は 6 になるはず"
assert multiply(0, 5) == 0, "0 * 5 は 0 になるはず"
print("すべてのテストが成功しました!")
def add(a, b):
return a + b
def multiply(a, b):
return a * b
# テストの実行
try:
test_calculation_functions()
except AssertionError as e:
print(f"テストが失敗しました:{e}")
課題 1. 入力ミスがあっても止まらず再入力を促す計算プログラム
入力ミスがあっても止まらず再入力を促す計算プログラム
def get_number(prompt):
"""数値を安全に入力させる関数"""
while True:
try:
value = int(input(prompt))
return value
except ValueError:
print("数字を入力してください")
def safe_calculator():
"""エラーに強い電卓プログラム"""
while True:
try:
# 数値の入力
num1 = get_number("1つ目の数字を入力:")
num2 = get_number("2つ目の数字を入力:")
# 演算子の入力
operator = input("演算子を入力(+, -, *, /):")
# 計算実行
if operator == "+":
result = num1 + num2
elif operator == "-":
result = num1 - num2
elif operator == "*":
result = num1 * num2
elif operator == "/":
if num2 == 0:
print("0での割り算はできません")
continue
result = num1 / num2
else:
print("無効な演算子です")
continue
# 結果表示
print(f"結果:{result}")
# 継続確認
if input("続けますか?(y/n):") != "y":
break
except Exception as e:
print(f"エラーが発生しました:{e}")
print("もう一度試してください")
# プログラムの実行
safe_calculator()
課題 2. 存在しないファイルを開こうとしたときにエラーを回避するプログラム
存在しないファイルを開こうとしたときにエラーを回避するプログラム
def safe_file_reader(filename):
"""ファイルを安全に読み込む関数"""
try:
with open(filename, "r", encoding="utf-8") as file:
content = file.read()
return content
except FileNotFoundError:
print(f"ファイル '{filename}' が見つかりません")
return None
except PermissionError:
print(f"ファイル '{filename}' にアクセスする権限がありません")
return None
except Exception as e:
print(f"予期せぬエラーが発生しました:{e}")
return None
def process_file():
"""ファイル処理プログラム"""
while True:
filename = input("処理するファイル名を入力してください:")
# ファイルの読み込み
content = safe_file_reader(filename)
if content is not None:
# ファイルの内容を処理
print("\nファイルの内容:")
print(content)
# 文字数をカウント
char_count = len(content)
line_count = len(content.splitlines())
print(f"\n文字数:{char_count}")
print(f"行数:{line_count}")
# 継続確認
if input("\n他のファイルを処理しますか?(y/n):") != "y":
break
# プログラムの実行
process_file()
# チャレンジ:
# - ファイルの内容を別のファイルにコピーする機能を追加
# - ファイルの内容を行ごとに分析する機能を追加
# - 複数のファイルを一度に処理する機能を追加
まとめ
この章で学んだこと:
- エラーは学習の機会として捉える
- try-exceptでエラーに対応できる
- デバッグ方法の使い分け
- コードの整理でバグを防ぐ
- テストでプログラムの品質を保つ
次の章では、データの処理と可視化について学び、より実践的なプログラミングスキルを身につけます!