LoginSignup
8
6

More than 5 years have passed since last update.

エラーの分類 (python3.x)とDebuggingメモ

Last updated at Posted at 2016-01-05

過去にも少しだけ触れたが、もっと分かりやすく解説してくれている記事を見つけたので復習の意味も込めて。大先輩のブログより転載, aka all credit belongs to our legendary cs alumni

Traceback message

Traceback (most recent call last):
  File "<pyshell#29>", line 3 in <module>
    result = buggy(5)
  File <pyshell#29>", line 5 in buggy
    return f + x
TypeError: unsupported operand type(s) for +: 'function' and 'int'

traceback messageのはエラーが起きた時系列順に経緯を辿ってプリントしてくれる。一番下が最も新しい。traceback messageは2つで一組の構成になっている。1つ目File "<pyshell#29>", line 3 in <module>はエラーを含んでいるファイルの名前、どこに(何番目のライン)にそのエラーがあるのか、そしてそのエラーを含んでいる関数名の3つをFile "<file name>", line <number>, in <function>というフォーマットで表している。2つ目result = buggy(5)はそのままだがその実際のコードを表示している。

Error messages

一番最後の行に書かれているのがerror messageである。error message<error type>: <error message>はエラーの種類(syntaxerror, typeerror etc)とエラーの詳細のフォーマットで記載されている。

Debugging

Doctestでとりあえず動かしてみる

def foo(x):
    """A random function.

    >>> foo(4)
    4
    >>> foo(5)
    5
    """

terminal上よりpython3 -m doctest file.py
python3 -m doctest file.py -vを使えばどのテストがパスしてどこが引っかかったかを教えてくれる。

通例としては最初の一行目で具体的にその関数が何をするのかを書き、一行ブランクを空ける。詳細な説明はこちら

もしdoctestの対象がsingle statement(=a single line that doesn't end in a :)の場合は"run_docstring_examples"と呼ばれるdoctest関数をつかう。この関数は3つの引数を持ちあわせている。1つめはテストしたい関数名、2つめはglobal()(=a built-in function that returns the global environment)、そして3つめがTrue(to indicate that we would like "verbose" output: a catalog of all tests run.)。ちなみにsingle statementをテストすることをunit testと呼ぶ。

Exhaustive unit testing is a hallmark of good program design.
- 良いプログラムデザインは包括的なunit testによって保証される。

それ以外にも自分自身でテスト関数を作ったり、新たにdoctestを作るってもよい。

Always run these doctests. Submitting an assignment without running doctests even once is practically throwing points away.

マジかよ。それは知らなかった(笑)

要所要所にprint()を挟んで経過を確認

def foo(x):
    result = some_function(x)
    return result // 5

というコードを書いたとしてどこにエラーがあるのかわからない場合はとりあえず結果をprintさせてみる。

def foo(x):
    result = some_function(x)
    print('result is', result)
    return other_function(result)

そしてできればただprintさせるのではなく一言加えておくと忘れずに済む

print(tmp)   # harder to keep track
print('tmp was this:', tmp)  # easier

while loopの後に入れるのも効果的

i = 0
while i < n:
    i += func(i)
    print('i is', i)

テストが終わったらprintを消しておくのを忘れずに

Long-term debugging

プロジェクト単位になってくると時にはデバグを瞬時に行わないほうがいい場合もある。そういうときは以下のようにしておくと便利

debug = True

def foo(n):
i = 0
while i < n:
    i += func(i)
    if debug:
        print('i is', i)

もし毎回結果表示されるのが嫌ならばfalseに変えてしまえばよい。こういった使い方をする変数をflagと呼ぶ。

Types of error

Syntax Error

原因:

  • コードに問題あり
 File "file name", line number
    def incorrect(f)
                    ^
SyntaxError: invalid syntax

^が不適切なシンタックスを含んでいるコードを示している。何がおかしいのかは表示されないがその原因がどこにあるかは教えてくれる。Pythonはコードを走らせる前にまずこのsyntax errorがないかを確認する。

Indentation Error

原因:

  • コードのラインのインデントに問題有り
 File "file name", line number
    print('improper indentation')
IndentationError: unindent does not match any outer indentation level

不適切にインデントがなされているところを表示している。スペースとタブの機能の区別をはっきりと。

TypeError

原因:

  • operand(max, mul etc..)とprimitive operator(数字など)の使い方が不適切の場合。
TypeError: unsupported operand type(s) for +: 'function' and 'int'
  • 関数とオブジェクトがごっちゃになっている。
>>> square = 3
>>> square(3)
Traceback (most recent call last):
  ...
TypeError: 'int' object is not callable`
  • 引数の数に問題有り。
>>> add(3)
Traceback (most recent call last):
  ...
TypeError: add expected 2 arguments, got 1

NameError

原因:
- 定義されていない変数を使っているもしくは関数

File "file name", line number
  y = x + 3
NameError: global name 'x' is not defined

notes: ここでglobal nameと記されている理由はPythonがエラーを含む関数のローカル領域から最終的にグローバル領域に入っていくためである。

IndexError

原因:
- sequence(tuple, list, string)の渡せる数の限界を超えている。

File "file name", line number
  x[100]
IndexError: tuple index out of range

よくあるバグ

simple spelling mistakes

helloHelloHELLOということ。NameErrorと出てきた時はスペリングにミスがあるのかも。または間違えたスペリングで変数や関数を定義してしまっている場合もある。

Missing Parentheses

そのまんま括弧のつけ忘れなど

def fun():
    return foo(bar()   # missing a parenthesis here

fun()

この場合、pythonはSyntaxErrorと称し、括弧の問題がある行の一つ後の行を指す。

Missing close quotes

pythonが具体的に教えてくれるので見つけるのも簡単。

File "file name", line "number"
  return 'hi
           ^
SyntaxError: EOL while scanning string literal

EOL = "end of line"

= (assignment) vs. == (equality test)

=は変数を引き渡すときに、==は変数が同等かどうかを確かめるために使う。典型的なエラーは

if x = 3: # when should be "==" instead

Infinite Loops

whileループはそのコンディションが達成されるまで回り続けるので陥りやすい。

i = 0
while i < 10:
    print(i)
i, n = 0, 0
while i < 10:
    print(i)
    n += 1
8
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
6