記事ディレクトリ
序文
過去のレビュー:
- Python シリーズ チュートリアル – Python3 入門 (1)
- Pythonシリーズチュートリアル – Python3環境構築 (2)
- Python シリーズ チュートリアル – Python3 VScode (3)
- Pythonシリーズチュートリアル – Python3の基本文法 (4)
- Python シリーズ チュートリアル – Python3 の基本データ型 (5)
- Python シリーズ チュートリアル -- Python3 データ型変換 (6)
- Python シリーズ チュートリアル -- Python3 の派生 (7)
- Python シリーズ チュートリアル -- Python3 インタープリタとアノテーション (8)
- Python シリーズのチュートリアル -- Python3 演算子とは (9)
- Python シリーズ チュートリアル -- Python3 数値 (数値) (10)
- Python シリーズ チュートリアル -- Python3 文字列 (11)
- Python シリーズ チュートリアル -- Python3 リスト (12)
- Python シリーズ チュートリアル -- Python3 タプル (13)
- Python シリーズ チュートリアル -- Python3 辞書 (14)
- Python シリーズ チュートリアル -- Python3 コレクション (15)
- Python シリーズ チュートリアル -- Python3 条件付き制御 (16)
- Python シリーズ チュートリアル -- Python3 ループ ステートメント (17)
- Python シリーズ チュートリアル -- Python3 プログラミング ステップ 1 (18)
- Python シリーズ チュートリアル -- Python3 の派生 (19)
- Python シリーズ チュートリアル -- Python3 イテレータとジェネレータ (20)
- Python シリーズ チュートリアル -- Python3 関数 (21)
- Python シリーズ チュートリアル -- Python3 データ構造 (22)
- Python シリーズ チュートリアル -- Python3 モジュール (23)
- Python シリーズ チュートリアル -- Python3 の入力と出力 (24)
- Pythonシリーズチュートリアル -- Python3 File(ファイル)メソッド (25)
- Python シリーズ チュートリアル -- Python3 OS ファイル/ディレクトリ メソッド (26)
Python の初心者として、初めて Python プログラミングを学習するとき、これまで説明しなかったいくつかのエラー メッセージがよく表示されます。この章ではそれらについて説明します。
Python には、簡単に認識できる 2 種類のエラーがあります。構文エラーと例外です。
Pythonのassert(アサーション)は式を判定し、式の条件が偽の場合に例外をトリガーするために使用されます。
文法上の誤り
次の例に示すように、初心者は Python の文法エラーや解析エラーに遭遇することがよくあります。
>>> while True print('Hello world')
File "<stdin>", line 1, in ?
while True print('Hello world')
^
SyntaxError: invalid syntax
この例では、関数 print() の前にコロン : が欠落しているため、エラーがチェックされます。
パーサーは間違った行を指摘し、最初に見つかったエラーの位置に小さな矢印をマークします。
異常な
Python プログラムの構文が正しい場合でも、実行時にエラーが発生する場合があります。実行時に検出されるエラーは例外と呼ばれます。
ほとんどの例外はプログラムによって処理されず、ここにエラー メッセージの形式で表示されます。
例
>>> 10 * (1/0) # 0 不能作为除数,触发异常
Traceback (most recent call last):
File "<stdin>", line 1, in ?
ZeroDivisionError: division by zero
>>> 4 + spam*3 # spam 未定义,触发异常
Traceback (most recent call last):
File "<stdin>", line 1, in ?
NameError: name 'spam' is not defined
>>> '2' + 2 # int 不能与 str 相加,触发异常
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: can only concatenate str (not "int") to str
例外はさまざまなタイプで発生し、すべてメッセージの一部として出力されます。この例のタイプは、ZeroDivisionError、NameError、および TypeError です。
エラー メッセージの先頭部分には例外が発生したコンテキストが表示され、具体的な情報がコール スタックの形式で表示されます。
例外処理
試す/除外する
例外キャプチャでは、try/Except ステートメントを使用できます。
次の例では、ユーザーに有効な整数を入力させますが、(Control-C またはオペレーティング システムが提供するメソッドを使用して) プログラムを中断できるようにします。ユーザーによる割り込み情報により、KeyboardInterrupt 例外が発生します。
while True:
try:
x = int(input("请输入一个数字: "))
break
except ValueError:
print("您输入的不是数字,请再次尝试输入!")
try ステートメントは次のように機能します。
-
まず、try 節 (キーワード try とキーワードexcel の間の文) が実行されます。
-
例外が発生しない場合は、Except 句を無視し、try 句が実行された後に終了します。
-
try 句の実行中に例外が発生した場合、try 句の残りの部分は無視されます。例外タイプが、Except の後の名前と一致する場合、対応するExcept 句が実行されます。
-
例外がどの例外とも一致しない場合、例外は上位の try に渡されます。
try ステートメントには、さまざまな特定の例外を処理するための複数のException 句が含まれる場合があります。最大 1 つのブランチが実行されます。
ハンドラーは、対応する try 句の例外のみを処理し、他の try ハンドラーの例外は処理しません。
例外句は複数の例外を同時に処理でき、これらの例外はタプルとして括弧内に置かれます。次に例を示します。
except (RuntimeError, TypeError, NameError):
pass
最後の例外句は例外の名前を省略でき、ワイルドカードとして使用されます。このメソッドを使用すると、エラー メッセージを出力し、再度例外をスローできます。
import sys
try:
f = open('myfile.txt')
s = f.readline()
i = int(s.strip())
except OSError as err:
print("OS error: {0}".format(err))
except ValueError:
print("Could not convert data to an integer.")
except:
print("Unexpected error:", sys.exc_info()[0])
raise
試す/除く...その他
try/excel ステートメントにはオプションの else 句もあります。この句を使用する場合は、すべての else 句の後に配置する必要があります。
try 句で例外が発生しなかった場合、else 句が実行されます。
次の例では、try 文でファイルがオープンできるかどうかを判定し、ファイルをオープンするときに例外がなければ、else 部分で文を実行してファイルの内容を読み取ります。
for arg in sys.argv[1:]:
try:
f = open(arg, 'r')
except IOError:
print('cannot open', arg)
else:
print(arg, 'has', len(f.readlines()), 'lines')
f.close()
else 句を使用することは、すべてのステートメントを try 句に入れるよりも優れており、Except ではキャッチできない予期しない例外を避けることができます。
例外処理は、try 句で直接発生した例外を処理するだけでなく、句内で呼び出された関数 (間接的に呼び出された関数も含む) でスローされた例外も処理します。例えば:
>>> def this_fails():
x = 1/0
>>> try:
this_fails()
except ZeroDivisionError as err:
print('Handling run-time error:', err)
Handling run-time error: int division or modulo by zero
try-finally ステートメント
try-finally ステートメントは、例外が発生するかどうかに関係なく、最終コードを実行します。
次の例のfinally ステートメントは、例外が発生したかどうかに関係なく実行されます。
例
try:
demo()
except AssertionError as error:
print(error)
else:
try:
with open('file.log') as file:
read_data = file.read()
except FileNotFoundError as fnf_error:
print(fnf_error)
finally:
print('这句话,无论异常是否发生都会执行。')
例外をスローする
Python は、raise ステートメントを使用して、指定された例外を発生させます。
raise の構文形式は次のとおりです。
raise [Exception [, args [, traceback]]]
次の例では、x が 5 より大きい場合に例外をトリガーします。
x = 10
if x > 5:
raise Exception('x 不能大于 5。x 的值为: {}'.format(x))
上記のコードを実行すると例外がトリガーされます。
Traceback (most recent call last):
File "test.py", line 3, in <module>
raise Exception('x 不能大于 5。x 的值为: {}'.format(x))
Exception: x 不能大于 5。x 的值为: 10
発生させる唯一のパラメータは、スローされる例外を指定します。これは、例外または例外クラス (つまり、Exception のサブクラス) のインスタンスである必要があります。
これが例外をスローしたかどうかを知りたいだけで、それを処理したくない場合は、単純な raise ステートメントで例外を再度発生させることができます。
>>> try:
raise NameError('HiThere') # 模拟一个异常。
except NameError:
print('An exception flew by!')
raise
An exception flew by!
Traceback (most recent call last):
File "<stdin>", line 2, in ?
NameError: HiThere
ユーザー定義の例外
新しい例外クラスを作成することで、独自の例外を設定できます。例外クラスは Exception クラスを継承し、直接的または間接的に継承できます。次に例を示します。
>>> class MyError(Exception):
def __init__(self, value):
self.value = value
def __str__(self):
return repr(self.value)
>>> try:
raise MyError(2*2)
except MyError as e:
print('My exception occurred, value:', e.value)
My exception occurred, value: 4
>>> raise MyError('oops!')
Traceback (most recent call last):
File "<stdin>", line 1, in ?
__main__.MyError: 'oops!'
在这个例子中,类 Exception 默认的 __init__() 被覆盖。
当创建一个模块有可能抛出多种不同的异常时,一种通常的做法是为这个包建立一个基础异常类,然后基于这个基础类为不同的错误情况创建不同的子类:
class Error(Exception):
"""Base class for exceptions in this module."""
pass
class InputError(Error):
"""Exception raised for errors in the input.
Attributes:
expression -- input expression in which the error occurred
message -- explanation of the error
"""
def __init__(self, expression, message):
self.expression = expression
self.message = message
class TransitionError(Error):
"""Raised when an operation attempts a state transition that's not
allowed.
Attributes:
previous -- state at beginning of transition
next -- attempted new state
message -- explanation of why the specific transition is not allowed
"""
def __init__(self, previous, next, message):
self.previous = previous
self.next = next
self.message = message
ほとんどの例外名は、標準の例外名と同様に「Error」で終わります。
クリーンアップ動作を定義する
try ステートメントには別のオプションの句があり、状況に関係なく実行されるクリーンアップ動作を定義します。例えば:
>>> try:
... raise KeyboardInterrupt
... finally:
... print('Goodbye, world!')
...
Goodbye, world!
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
KeyboardInterrupt
上記の例では、try 句に例外があるかどうかに関係なく、finally 句が実行されます。
Try 句 (または、Except 句と Else 句) で例外がスローされ、それをキャッチする例外がない場合、その例外は、finally 句の実行後にスローされます。
より複雑な例を次に示します (同じ try ステートメント内の例外句と Final 句)。
>>> def divide(x, y):
try:
result = x / y
except ZeroDivisionError:
print("division by zero!")
else:
print("result is", result)
finally:
print("executing finally clause")
>>> divide(2, 1)
result is 2.0
executing finally clause
>>> divide(2, 0)
division by zero!
executing finally clause
>>> divide("2", "1")
executing finally clause
Traceback (most recent call last):
File "<stdin>", line 1, in ?
File "<stdin>", line 3, in divide
TypeError: unsupported operand type(s) for /: 'str' and 'str'
事前定義されたクリーンアップ動作
一部のオブジェクトでは、システムが正常に使用するかどうかに関係なく、不要になったときに実行される標準のクリーンアップ動作が定義されています。
次の例は、ファイルを開いて内容を画面に出力する試みを示しています。
for line in open("myfile.txt"):
print(line, end="")
上記のコードの問題は、実行が完了してもファイルが開いたままで閉じられないことです。
キーワード with ステートメントを使用すると、ファイルなどのオブジェクトが使用後にクリーンアップ メソッドを正しく実行することを保証できます。
with open("myfile.txt") as f:
for line in f:
print(line, end="")
上記のコードを実行すると、処理中に何か問題が発生した場合でも、ファイル f は常に閉じられます。