エラーはともだち こわくないよ
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 2NameErrorの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 zeroPython 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
 
