エラーはともだち こわくないよ
Takanori Suzuki
みんなのPython勉強会 #112 / 2025 Feb 13
今日はなすこと
Pythonのエラーってなに?
よくあるエラーのパターン
例外処理
おまけ:better error messages
今日のゴール
Pythonのエラーが嫌いじゃなくなる
エラーと仲良くなれる
Photos 📷 Tweets 🐦 👍
#stapy / @takanory
slides.takanory.net 💻

Who am I? / お前 誰よ 👤
Takanori Suzuki / 鈴木 たかのり ( @takanory)
BeProud 取締役 / Python Climber
PyCon JP Association 代表理事
Python Boot Camp 講師、Python mini Hack-a-thon 主催、Pythonボルダリング部 部長

PyCon JP Association 🐍
日本国内のPythonユーザのために、Pythonの普及及び開発支援を行うために、継続的にカンファレンス(PyCon)を開くことを目的とした 非営利組織

PyCon JP 2025
🗓️ 2025年9月26日(金)-27日(土)
⛩️ 広島国際会議場
旅費の支援も多分あるよ
BeProud Inc. 🏢
BeProud: Pythonシステム開発、コンサル
connpass: IT勉強会支援プラットフォーム
PyQ: Python独学プラットフォーム
TRACERY: システム開発ドキュメントサービス

BeProudメンバー募集中 
Pythonのエラーってなに? 
エラー好きな人? 
エラー嫌いな人? 
Pythonには2種類のエラー
構文エラー(syntax error)
例外(exception)
構文エラー(syntax error)
Pythonの構文として正しくない
構文解析時にエラーが発生
>>> for i in range(10)
  File "<python-input-1>", line 1
    for i in range(10)
                      ^
SyntaxError: expected ':'
例外(exception)
構文は正しい
実行時にエラーが発生
>>> 1 / 0
Traceback (most recent call last):
  File "<python-input-0>", line 1, in <module>
    1 / 0
    ~~^~~
ZeroDivisionError: division by zero
エラーが怖い?
エラーは怒っていない
ここが問題だよと教えてくれている
問題を修正するための案内役
エラーは怒っていない
for i in range(10)
    print(i)
% python3.13 error_example.py 
  File ".../error_example.py", line 1  # このファイルの1行目の
    for i in range(10)
                      ^  # この場所で
SyntaxError: expected ':'  # 構文エラーが発生:`:`がここに必要
エラーの意味がわからない?
Googleで検索 

AIに質問 

長いエラーが出たらうわってなる? 
大事なのは一番最後
>>> from urllib import request
>>> request.urlopen("https://httpbin.org/status/403")
Traceback (most recent call last):
  File "<python-input-1>", line 1, in <module>
    request.urlopen("https://httpbin.org/status/403")
    ~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File ".../urllib/request.py", line 189, in urlopen
    return opener.open(url, data, timeout)
           ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^
  File ".../urllib/request.py", line 495, in open
    response = meth(req, response)
  File ".../urllib/request.py", line 604, in http_response
    response = self.parent.error(
        'http', request, response, code, msg, hdrs)
  File ".../urllib/request.py", line 533, in error
    return self._call_chain(*args)
           ~~~~~~~~~~~~~~~~^^^^^^^
  File ".../urllib/request.py", line 466, in _call_chain
    result = func(*args)
  File ".../urllib/request.py", line 613, in http_error_default
    raise HTTPError(req.full_url, code, msg, hdrs, fp)
urllib.error.HTTPError: HTTP Error 403: Forbidden
そのうち自分でエラーに対処できる 
 (ようになるはず)
よくあるエラーのパターン 
書籍からエラーの例を引用【AD】
書籍からエラーの例を引用【AD】
2024年10月31日発売、価格:3,630円
Eric Matthes著
鈴木たかのり、安田善一郎翻訳
大絶賛発売中!!
どんなエラーが出る?(p18)
message = "こんにちは、Start Python Clubのみなさん!"
print(mesage)
どんなエラーが出る?(p18)
Traceback (most recent call last):
  File ".../message.py", line 2, in <module>
    print(mesage)
          ^^^^^^
NameError: name 'mesage' is not defined. \
    Did you mean: 'message'?
NameError:名前が見つからないエラー'mesage'という名前は定義されていません'message'と間違えてませんか?
どんなエラーが出る?(p18)
変数名を修正して解決
message = "こんにちは、Start Python Clubのみなさん!"
# print(mesage)
print(message)
どんなエラーが出る?(p27)
message = 'Start Python Club's member'
print(message)
どんなエラーが出る?(p27)
  File ".../message2.py", line 1
    message = 'One of Python's strengths is its diverse community.'
                                                                  ^
SyntaxError: unterminated string literal (detected at line 1)
SyntaxError:構文エラー文字列リテラルが終了していません
どんなエラーが出る?(p27)
クォーテーションを変更して解決
message = "Start Python Club's member"
print(message)
どんなエラーが出る?(p52)
beers = ['Pilsner', 'Pale Ale', 'IPA']
print(beers[3])
どんなエラーが出る?(p52)
  File ".../beers.py", line 2, in <module>
    print(beers[3])
          ~~~~~^^^
IndexError: list index out of range
IndexError:インデックスエラーインデックスが範囲外です
どんなエラーが出る?(p52)
正しい範囲を指定して解決
beers = ['Pilsner', 'Pale Ale', 'IPA']
print(beers[2])
どんなエラーが出る?(p60)
beers = ['Pilsner', 'Pale Ale', 'IPA']
for beer in beers:
print(beer)
どんなエラーが出る?(p60)
  File ".../beers2.py", line 3
    print(beer)
    ^^^^^
IndentationError: expected an indented block after \
    'for' statement on line 2
IndentationError:正しくないインデントのエラー2行目の
for文のあとにインデントが必要
どんなエラーが出る?(p60)
インデントを追加して解決
beers = ['Pilsner', 'Pale Ale', 'IPA']
for beer in beers:
    print(beer)
どんなエラーが出る?(p61)
beers = ['Pilsner', 'Pale Ale', 'IPA']
for beer in beers
    print(beer)
どんなエラーが出る?(p61)
  File ".../beers3.py", line 2
    for beer in beers
                     ^
SyntaxError: expected ':'
SyntaxError:構文エラー:が必要です
どんなエラーが出る?(p61)
末尾に
:を追加して解決
beers = ['Pilsner', 'Pale Ale', 'IPA']
for beer in beers:
    print(beer)
どんなエラーが出る?(p76)
sizes = ("US Pint", "Half Pint")
sizes[0] = "UK Pint"
どんなエラーが出る?(p76)
Traceback (most recent call last):
  File ".../sizes.py", line 2, in <module>
    sizes[0] = "UK Pint"
    ~~~~~^^^
TypeError: 'tuple' object does not support item assignment
TypeError:データ型に関するエラータプルは要素の代入に対応していません
どんなエラーが出る?(p76)
タプル全体を上書きは可能
sizes = ("US Pint", "Half Pint")
# サイズを変更
sizes = ("UK Pint", "Half Pint")
どんなエラーが出る?(p113)
beer = {"name": "Punk IPA", "brewery": "Brewdog"}
print(beer["style"])
どんなエラーが出る?(p113)
Traceback (most recent call last):
  File ".../beer_dict.py", line 2, in <module>
    beer["style"]
    ~~~~^^^^^^^^^
KeyError: 'style'
KeyError:辞書のキーが存在しないエラー
どんなエラーが出る?(p113)
get()メソッドを使用する
beer = {"name": "Punk IPA", "brewery": "Brewdog"}
print(beer.get("style", "スタイルは不明です"))
どんなエラーが出る?(p134)
age = input("何歳ですか?")
if age >= 20:
    print("お酒が飲める年齢です")
else:
    print("お酒は飲めません")
% python3.13 age.py
何歳ですか?21
どんなエラーが出る?(p134)
% python3.13 age.py
何歳ですか?21
Traceback (most recent call last):
  File ".../age.py", line 2, in <module>
    if age >= 20:
       ^^^^^^^^^
TypeError: '>=' not supported between instances of \
    'str' and 'int'
TypeError:データ型に関するエラーstrとintの間で
>=はサポートされていません
どんなエラーが出る?(p134)
int()で整数に変換する
age = input("何歳ですか?")
if int(age) >= 20:
    print("お酒が飲める年齢です")
else:
    print("お酒は飲めません")
% python3.13 age.py
何歳ですか?21
お酒が飲める年齢です
どんなエラーが出る?(p157)
def describe_beer(beer_name, brewery):
    """ビールについての情報を出力する"""
    print(f"{beer_name}は{brewery}で作られています")
describe_beer()
どんなエラーが出る?(p157)
Traceback (most recent call last):
  File ".../beer_func.py", line 5, in <module>
    describe_beer()
    ~~~~~~~~~~~~~^^
TypeError: describe_beer() missing 2 required positional \
    arguments: 'beer_name' and 'brewery'
TypeError:データ型に関するエラー2つの位置引数beer_nameとbreweryがありません
どんなエラーが出る?(p157)
引数を正しく指定する
def describe_beer(beer_name, brewery):
    """ビールについての情報を出力する"""
    print(f"{beer_name}は{brewery}で作られています")
describe_beer("よなよなエール", "ヤッホー")
何個わかりました?
エラーの一覧
初めて見る例外があったら調べてみよう!
さまざまな例外が発生する 
例外が発生しても正しく動作させたい 
例外を処理する 
例外処理の基本
数値以外を指定すると
ValueErrorが発生
age = input("何歳ですか?")
if int(age) >= 20:
    print("お酒が飲める年齢です")
else:
    print("お酒は飲めません")
% python3.13 age.py
何歳ですか?二十歳
Traceback (most recent call last):
  File "...//age.py", line 2, in <module>
    if int(age) >= 20:
       ~~~^^^^^
ValueError: invalid literal for int() with base 10: '二十歳'
例外処理の基本
tryとexceptで例外処理
% python3.13 age2.py
何歳ですか?二十歳
数値を入力してください
age = input("何歳ですか?")
try:
    if int(age) >= 20:
        print("お酒が飲める年齢です")
    else:
        print("お酒は飲めません")
except ValueError:
    print("数値を入力してください")
例外処理の基本
例外がなければ
except節は実行されない
% python3.13 age2.py
何歳ですか?21
お酒が飲める年齢です
age = input("何歳ですか?")
try:
    if int(age) >= 20:
        print("お酒が飲める年齢です")
    else:
        print("お酒は飲めません")
except ValueError:
    print("数値を入力してください")
複数の例外に対応する
1つの処理で異なる種類の例外が発生する場合がある
ファイルからテキストを読み込む場合
どんな例外が考えられますか?
from pathlib import Path
p = Path("beer.txt")
text = p.read_text(encoding="utf-8")  # ここで例外発生
複数の例外に対応する
例外の種類によってメッセージを出し分け
from pathlib import Path
p = Path("beer.txt")
try:
    text = p.read_text(encoding="utf-8")
except FileNotFoundError:
    print("ファイルが存在しません")
except PermissionError:
    print("ファイルの読み込み権限がありません")
except UnicodeDecodeError:
    print("utf-8のテキストじゃありません")
事前チェックと例外処理
事前にチェックして例外を防げる場合もある
どちらを使うかはお好みで
from pathlib import Path
p = Path("beer.txt")
if not p.exists():  # ファイルの存在チェック
    print("ファイルが存在しません")
else:
    ...
	
if key in beer_dict:  # キーの存在チェック
    beer_dict[key]
else:
    ...
辞書のgetは適切に使おう
キー名をtypoしているのに気づかないことも
[]なら例外で気づける型ヒントで
TypedDictを使うのもあり
style = beer.get("stlye")  # typoに気づかない
class Beer(TypedDict):
    name: str
    style: str
beer: Beer = {"name": "Stone IPA", "style": "IPA"}
例外を握りつぶさない
例外を隠蔽するとエラーの原因がわからなくなる
from pathlib import Path
p = Path("beer.txt")
try:
    text = p.read_text(encoding="utf-8")  # ここで例外発生
except Exception:
    pass  # なにが問題かわからなくなる
try節は短く書く
エラー発生時に問題を切り分けられない
from pathlib import Path
p = Path("beer.txt")
try:
    text = p.read_text(encoding="utf-8")  # ファイル読み込みエラー
    for line in text.splitlines():
        name, price_text = line.split(",")  # 分割エラー
        price = int(price_text)  # 変換エラー
        # なにか他の処理
        ...
except Exception:
    print("エラーが発生しました")
try節は短く書く
tryの範囲を短く
from pathlib import Path
p = Path("beer.txt")
try:
    text = p.read_text(encoding="utf-8")  # ファイル読み込みエラー
except Exception:
    print("ファイルの読み込みに失敗しました")
else:
    for line in text.splitlines():
        try:
            name, price_text = line.split(",")  # 分割エラー
            price = int(price_text)  # 変換エラー
        except ValueError as e:
            print(f"データ変換エラーが発生: {e}")
        # なにか他の処理
        ...
try節は短く書く
{e}で例外を見分ける
    for line in text.splitlines():
        try:
            name, price_text = line.split(",")  # 分割エラー
            price = int(price_text)  # 変換エラー
        except ValueError as e:
            print(f"データ変換エラーが発生: {e}")
# "aaaa" などカンマがない場合
データ変換エラーが発生: not enough values to unpack (expected 2, got 1)
# "aaaa,bbbb" など2番目の要素が数字じゃない
データ変換エラーが発生: invalid literal for int() with base 10: 'b'
適切な例外処理をしよう! 
おまけ:better error messages 
better error messagesとは
Python 3.10から追加
エラーメッセージをよりわかりやすく
閉じカッコ忘れ
beers = ["Punk IPA", "よなよなエール",
beer = beers[0]
Python 3.9だとエラーが意味不明
% Python 3.9 unclosed.py
  File ".../unclosed.py", line 2
    beer = beers[0]
         ^
SyntaxError: invalid syntax
閉じカッコ忘れ
beers = ["Punk IPA", "よなよなエール",
beer = beers[0]
Python 3.10だとわかりやすい!
% Python 3.10 unclosed.py
  File ".../unclosed.py", line 1
    beers = ["Punk IPA", "よなよなエール",
            ^
SyntaxError: '[' was never closed
末尾の: 忘れ
beers = ['Pilsner', 'Pale Ale', 'IPA']
for beer in beers
    print(beer)
% python3.9 beers3.py
  File ".../beers3.py", line 2
    for beer in beers
                     ^
SyntaxError: invalid syntax  # 無効なシンタックス
% python3.10 beers3.py
  File ".../beers3.py", line 2
    for beer in beers
                     ^
SyntaxError: expected ':'  # ':'を忘れてません?
インデント忘れ
beers = ['Pilsner', 'Pale Ale', 'IPA']
for beer in beers:
print(beer)
% python3.9 beers2.py
  File ".../beers2.py", line 3
    print(beer)
    ^
IndentationError: expected an indented block
% python3.10 beers2.py
  File ".../beers2.py", line 3
    print(beer)
    ^
IndentationError: expected an indented block after 'for' statement on line 2
NameErrorのDid you mean
message = "こんにちは、Start Python Clubのみなさん!"
print(mesage)
% python3.9 message.py
  File ".../message.py", line 3
    print(mesage)
NameError: name 'mesage' is not defined
% python3.10 message.py
  File ".../message.py", line 3
    print(mesage)
NameError: name 'mesage' is not defined. \
    Did you mean: 'message'?
Python 3.11での改善
Python 3.11: PEP 657: トレースバックのエラー位置の詳細化
例外の発生箇所がわかりやすい!!
>>> x, y, z = 1, 1, 0
>>> x / y / z
Traceback (most recent call last):
  File "<python-input-1>", line 1, in <module>
    x / y / z
    ~~~~~~^~~
ZeroDivisionError: float division by zero
Python 3.12での改善
Python 3.12: Improved Error Messages
関数、
ImportErrorなどでも提案が追加
>>> random.randint()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'random' is not defined. \
    Did you forget to import 'random'?
>>> from datetime import datatime
Traceback (most recent call last):
  File "<python-input-6>", line 1, in <module>
    from datetime import data
ImportError: cannot import name 'data' from 'datetime' (...). \
    Did you mean: 'date'?
Python 3.13での改善
Python 3.13: Improved error messages
引数もDid you meanで提案
>>> f = open("beer.txt", encodeng="utf-8")
Traceback (most recent call last):
  File "<python-input-7>", line 1, in <module>
    f = open("beer.txt", encodeng="utf-8")
TypeError: open() got an unexpected keyword argument 'encodeng'. \
    Did you mean 'encoding'?
エラーメッセージが改善されている
新しいバージョンを使おう 
まとめ 
エラーが出たら調べる
そのうち読めるようになる
よくあるエラーを紹介
NameError、SyntaxError、IndexError、IndentationError、TypeError、KeyError
例外処理の基本と気をつけるポイント
エラーとともだちになれそう? 
お知らせ
Sphinxドキュメントにネコチャン絵文字を簡単に入れられる拡張sphinx-nekochanをリリースしました
参考:【2024.08追加】SlackやDiscordで使えるネコチャン絵文字を配布しています♪|しかまつ(ネコチャン絵文字職人)
Thank You 
takanory takanory takanory takanory
