【Python】例外処理把握によるエラーの特定
概要
システム開発に携わるデベロッパーであれば、誰しもデバッグに頭を悩ませることが多いだろう。特にデバッグするためのエラー内容特定について、時間がかかる人が多いのではないか。かく言う自分もそうである。システム開発歴が短いため、「これって、どう言うエラー??」とか「どこに原因があるの??」と問題分析ができず、時間を空費してしまうことが多々あった。コードを書くうえで、避けるべきエラー出力の方法と良いエラー出力の方法を記載する。
避けるべきエラー出力の方法
結論から言うと、下記が避けるべきエラー出力の方法である。
except:
return json.dumps({
'success': False,
'error': "Error with creating a new drink"
}), 500
なぜこの方法を避けるべきかというと、エラーが発生しても500エラーとしか表示されないからである。このような不明なエラーをデバッグするためには、例外処理の出力方法を改善する必要がある。具体的なエラーメッセージを表示することで、エラーの原因を特定しやすくなる。
良いエラー出力の方法
良いエラー出力の方法は下記である。
except Exception as e:
return json.dumps({
'success': False,
'error': f"Error with creating a new drink: {str(e)}"
}), 500
上記内容だと、exceptブロックで例外をキャッチして、その例外を変数eに代入してエラーメッセージを表示させている。そのため、問題が起こった時に、その問題の詳細情報を確認できるため、問題解決しやすくなる。
例外処理の一例
自分の場合、下記エラーが起こった際に、エラー特定に時間がかかっていた。やろうとしていることは、単純にbodyの内容をdrinkテーブルに対してPOSTするだけである。ただ問題が起こっても、500エラーとしか表示されないので、原因特定ができない。
@app.route('/drinks', methods=['POST'])
@requires_auth('post:drinks')
def post_drinks_detail(payload):
body = {
'id': 2,
'title': 'banana',
'recipe': [{'name': 'water', 'color': 'blue', 'parts': 1}]
}
try:
id = body.get('id')
title = body.get('title')
recipe = json.dumps(body.get('recipe'))
new_drink = Drink(id=id, title=title, recipe=recipe)
print(new_drink)
new_drink.insert()
return jsonify({
'success': True,
'drinks': [new_drink.long()]
}), 200
except:
return json.dumps({
'success': False,
'error': "Error with creating a new drink"
}), 500
末尾に下記を追記したところ、具体的なエラー表示がされた。
except Exception as e:
return json.dumps({
'success': False,
'error': f"Error with creating a new drink: {str(e)}"
}), 500
エラー内容は、下記の通り。表示されたエラーによると、データベースの一意性制約が違反されたと示されている。具体的にはdrink.title列に一意性制約があり、既にwaterというタイトルが存在するため、同じタイトルを挿入しようとするとエラーが発生する。
{"success": false, "error": "Error with creating a new drink: (sqlite3.IntegrityError) UNIQUE constraint failed:
drink.title\n[SQL: INSERT INTO drink (id, title, recipe) VALUES (?, ?, ?)]\n[parameters: (2, 'water', '[{\"name\":
\"water\", \"color\": \"blue\", \"parts\": 1}]')]\n(Background on this error at: http://sqlalche.me/e/gkpj)"}
そのため、下記の通り問題解決できることがわかった。
- 既存レコードを削除もしくは変更して、新しいレコードの追加を可能とする
- 新しいレコードのタイトルを変更して、一意性制約を満たす
- データベースのスキーマを変更して、一意性制約を削除または変更する
今後に向けて
下記の通り、例外処理エラーの詳細を表示して、その内容をchatGPTで聞くのが一番早い気がする。
except Exception as e:
print(e)
return json.dumps({
'success': False,
'error': f"Error with creating a new drink: {str(e)}"
}), 500
Discussion