Python の 2 つのエラー タイプの紹介

零下一度
リリース: 2017-07-23 14:06:03
オリジナル
3589 人が閲覧しました

これまでエラー メッセージについてはあまり述べてきませんでしたが、いくつかの例で使用されています。 Python には少なくとも 2 種類のエラーがあります: 構文エラー例外

8.1 構文エラー

構文エラーは、解析エラーとも呼ばれ、Python 初心者の間でよくある苦情です。

>>> while True print('Hello world')
  File "<stdin>", line 1while True print(&#39;Hello world&#39;)                   ^SyntaxError: invalid syntax
ログイン後にコピー

Python パーサーはエラー行を繰り返し出力し、エラー行内で最初にエラーが検出された位置を指す小さな矢印を表示します。エラーは矢印の前のステートメントによって発生します (少なくともそれが検出されています): 上記の例では、コロン :< により、エラーは <code>print() 関数で検出されます。 /code> がありません。ファイル名と行番号も出力されるため、プログラムがスクリプトから作成された場合に問題を見つけやすくなります。 print()函数被侦测到,因为在它之前的冒号:缺失了。文件名和行号也被打印出来,当程序来自脚本时可以方便定位问题。

8.2 Exceptions

即使语句或者表达式在语法上是正确的,但是在执行的时候也可能会发生错误。在执行期间侦测到的问题叫做异常,异常不是绝对的致命错误:接下来会介绍如何在Python中处理异常。然而大多数异常都不会被程序处理,它们最终会成为错误信息,展示如下:

>>> 10 * (1/0)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>ZeroDivisionError: division by zero>>> 4 + spam*3Traceback (most recent call last):
  File "<stdin>", line 1, in <module>NameError: name &#39;spam&#39; is not defined>>> &#39;2&#39; + 2Traceback (most recent call last):
  File "<stdin>", line 1, in <module>TypeError: Can&#39;t convert &#39;int&#39; object to str implicitly
ログイン後にコピー

最后一行错误信息指出发生了什么。异常有不同类型,类型也作为错误信息的一部分打印出来:以上示例中的类型有除零异常ZeroDivisionError, 名字异常NameError 以及类型异常TypeError。作为异常类型打印的字符串是built-in异常的名字。对于所有built-in异常来说都是如此,尽管这个约定很有用,但是并不是所有用户自定义异常都会遵守。标准异常名字是built-in标识符(不是保留字)。

剩余行基于异常类型展示了详细的信息以及异常发生的原因。

前面部分错误信息以堆栈回溯的方式,展示异常发生的上下文信息。通常堆栈回溯中列出了源代码行;然而,当程序是从标准输入中读取时,不会展示行。

Built-in异常列举了所有built-in异常以及它们的意义。

8.3 Handling Exceptions

Python程序允许处理指定异常。以下程序要求用户循环输入,直到输入为有效整数停止,但是也可以中断程序(使用Control-C或者其他操作系统支持的手段);注意用户诱发的中断会抛出KeyboardInterrupt异常。

while True:try:
        x = int(input("Please enter a number: "))breakexcept ValueError:print("Oops!  That was no valid number.  Try again...")
ログイン後にコピー

try语句的执行顺序为:

  • 首先,执行在tryexcept之间的try子句

  • 如果没有异常发生,跳过except子句try语句执行完毕

  • 如果try子句执行期间有异常发生,该子句内剩余语句被跳过。接下来如果抛出的异常类型可以与关键字except后的异常匹配,那么except子句执行,接着继续执行try语句后的语句。

  • 如果异常发生但是没有匹配到except后的异常,那么异常抛到外层try语句;如果异常得不到处理,该异常成为未处理异常,导致程序终止并且像以上示例一样打印信息。

一个try语句可以有多个except子句,为不同的异常指定处理方法。至多只有一个except子句会被执行。处理程序只会处理发生在对应try子句中的异常,而不会处理发生在同一try语句中其他处理程序中的异常。一个except子句可以使用带括号的元组列出多个异常,就像这样:

... except (RuntimeError, TypeError, NameError):
...     pass
ログイン後にコピー

except子句中的类可以匹配类型是其子类或者它自己类型的异常(但反过来不行,except子句中的子类不会匹配父类异常)。例如以下代码会依次打印B, C, D:

class B(Exception):passclass C(B):passclass D(C):passfor cls in [B, C, D]:try:raise cls()except D:print("D")except C:print("C")except B:print("B")
ログイン後にコピー

注意以上的except子句若反过来写(except B在前),那么将会打印B, B, B ——第一个except子句的匹配被触发。

最后一个except子句可以省略异常名字作为通配符。因为这样做会隐藏其他的真实程序错误,所有要谨慎使用。也可以用来打印错误信息并且重新抛出(允许调用者处理异常):

import systry:
    f = open(&#39;myfile.txt&#39;)
    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...except语句有一个可选的else子句,该子句只能出现在所有except子句之后。若要求try子句没有抛出异常时必须执行一段代码,使用else子句很有用(译注:else子句会被return, break, continue

8.2 例外
ステートメントや式が文法的に正しい場合でも、実行中にエラーが発生する可能性があります。実行中に検出された問題は 🎜例外🎜 と呼ばれます。例外は絶対に致命的なエラーではありません。 次に、Python で例外を処理する方法を紹介します。ただし、ほとんどの例外はプログラムによって処理されず、最終的には以下に示すようなエラー メッセージになります。 🎜🎜
for arg in sys.argv[1:]:try:
        f = open(arg, &#39;r&#39;)except OSError:print(&#39;cannot open&#39;, arg)else:print(arg, &#39;has&#39;, len(f.readlines()), &#39;lines&#39;)
        f.close()
ログイン後にコピー
🎜🎜 エラー メッセージの最後の行は、何が起こったかを示します。例外にはさまざまなタイプがあり、そのタイプもエラー メッセージの一部として出力されます。上記の例のタイプは、ゼロ除算例外 ZeroDivisionError、名前例外 NameError</ です。 code> とタイプ例外 <code>TypeError 。例外タイプとして出力される文字列は、組み込み例外の名前です。これはすべての組み込み例外に当てはまります。この規則は便利ですが、すべてのユーザー定義例外がこれに従うわけではありません。標準例外名は組み込みの識別子です (予約語ではありません)。 🎜🎜残りの行には、例外の種類と例外が発生した理由に基づいた詳細情報が表示されます。 🎜🎜エラー メッセージの前の部分には、スタック トレースバックの形式で例外のコンテキスト情報が表示されます。通常、ソース コードの行はスタック トレースバックにリストされますが、プログラムが標準入力から読み取っている場合、その行は表示されません。 🎜🎜「組み込み例外」には、すべての組み込み例外とその意味がリストされています。 🎜🎜8.3 例外の処理🎜🎜Python プログラムでは、指定された例外を処理できます。次のプログラムでは、入力が有効な整数になるまで入力をループする必要がありますが、プログラムは中断することもできます (Control-C またはオペレーティング システムでサポートされているその他の手段を使用)。割り込みが発生すると、KeyboardInterrupt 例外がスローされます。 🎜🎜
>>> try:
...     raise Exception(&#39;spam&#39;, &#39;eggs&#39;)
... except Exception as inst:
...     print(type(inst))    # the exception instance...     print(inst.args)     # arguments stored in .args...     print(inst)          # __str__ allows args to be printed directly,...                          # but may be overridden in exception subclasses...     x, y = inst.args     # unpack args...     print(&#39;x =&#39;, x)
...     print(&#39;y =&#39;, y)
...<class &#39;Exception&#39;>(&#39;spam&#39;, &#39;eggs&#39;)
(&#39;spam&#39;, &#39;eggs&#39;)
x = spam
y = eggs
ログイン後にコピー
ログイン後にコピー
🎜🎜try ステートメントの実行順序は次のとおりです: 🎜
  • 🎜最初に、try を実行します。 < 🎜try 句🎜🎜
  • 🎜例外が発生しない場合は、code>excel 間の 🎜Except 句🎜 をスキップし、try ステートメントが実行されます🎜< /li>
  • 🎜try 句の実行中に例外が発生した場合、句内の残りのステートメントはスキップされます。次に、スローされた例外の種類がキーワード excel の後の例外と一致する場合は、Exception 節が実行され、try ステートメントの後のステートメントが引き続き実行されます。 🎜
  • 🎜例外が発生したが、Except の後に一致する例外がない場合、例外が処理できない場合、例外は外側の try ステートメントにスローされ、例外は 🎜 になります。未処理の例外 🎜 が発生したため、プログラムが終了し、上記の例のようなメッセージが表示されます。 🎜
🎜 try ステートメントには、さまざまな例外の処理方法を指定する複数のException句を含めることができます。最大で 1 つのExcept 句が実行されます。ハンドラーは、対応する try 句で発生した例外のみを処理し、同じ try ステートメント内の他のハンドラーで発生した例外は処理しません。例外句では、次のように括弧で囲まれたタプルを使用して複数の例外をリストできます。 🎜🎜
>>> def this_fails():
...     x = 1/0...>>> try:
...     this_fails()
... except ZeroDivisionError as err:
...     print(&#39;Handling run-time error:&#39;, err)
...
Handling run-time error: division by zero
ログイン後にコピー
ログイン後にコピー
🎜🎜 excel 句のクラスは、そのサブクラスまたは独自の型例外である型と一致できます (ただし、逆に、excel 節のサブクラスは親クラスの例外と一致しません)。たとえば、次のコードは B、C、D を順番に出力します: 🎜🎜
>>> raise NameError(&#39;HiThere&#39;)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>NameError: HiThere
ログイン後にコピー
ログイン後にコピー
🎜🎜 上記のException節が逆に書かれている場合(Except Bが最初)、B、B、 B が出力されます -- 最初の例外句の一致がトリガーされます。 🎜🎜最後の例外句では、ワイルドカードとして例外名を省略できます。これを行うと、他の実際のプログラム エラーが隠れてしまう可能性があるため、慎重に使用してください。エラー メッセージの出力と再スローにも使用できます (呼び出し元が例外を処理できるようにします): 🎜🎜
raise ValueError  # shorthand for &#39;raise ValueError()&#39;
ログイン後にコピー
ログイン後にコピー
🎜🎜try...Except ステートメントにはオプションの 🎜 else があります句🎜、この句は結局句を除いてのみ出現できます。 try 句が例外をスローしないときにコードのセクションを実行する必要がある場合は、else 句を使用すると便利です (注釈: else 句は、return、break、続行)。例: 🎜🎜
>>> try:
...     raise NameError(&#39;HiThere&#39;)
... except NameError:
...     print(&#39;An exception flew by!&#39;)
...     raise...
An exception flew by!Traceback (most recent call last):
  File "<stdin>", line 2, in <module>NameError: HiThere
ログイン後にコピー
ログイン後にコピー
🎜

使用 else 子句比在 try 子句中附加代码要好,因为这样可以避免 try ... except 意外的捕获的本不属于它们保护的那些代码抛出的异常。

异常发生时,可以携带与之关联的值,也称作异常参数。异常参数是否可以存在以及其类型取决于异常类型。

except子句可以在异常名字后指定变量。该变量绑定到异常实例,异常参数存储在instance.args属性中。方便起见,异常实例定义了__str__()以便异常参数可以直接打印,而不是使用.args引用。也可以首先实例化异常,并在抛出它之前加入任何想要的参数:

>>> try:
...     raise Exception(&#39;spam&#39;, &#39;eggs&#39;)
... except Exception as inst:
...     print(type(inst))    # the exception instance...     print(inst.args)     # arguments stored in .args...     print(inst)          # __str__ allows args to be printed directly,...                          # but may be overridden in exception subclasses...     x, y = inst.args     # unpack args...     print(&#39;x =&#39;, x)
...     print(&#39;y =&#39;, y)
...<class &#39;Exception&#39;>(&#39;spam&#39;, &#39;eggs&#39;)
(&#39;spam&#39;, &#39;eggs&#39;)
x = spam
y = eggs
ログイン後にコピー
ログイン後にコピー

对于未处理异常来说,如果它有参数,那么参数将在错误信息的后面部分(详细信息部分)打印。

异常处理程序不仅仅会处理即时发生在try子句中的异常,还会处理try子句中直接或者间接调用的函数中发生的异常。例如:

>>> def this_fails():
...     x = 1/0...>>> try:
...     this_fails()
... except ZeroDivisionError as err:
...     print(&#39;Handling run-time error:&#39;, err)
...
Handling run-time error: division by zero
ログイン後にコピー
ログイン後にコピー

8.4 Raising Exceptions

raise语句允许程序员强制发生异常。例如:

>>> raise NameError(&#39;HiThere&#39;)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>NameError: HiThere
ログイン後にコピー
ログイン後にコピー

raise的唯一参数指定要抛出的异常。参数必须是异常实例或者异常类(继承自Exception类的子类)。如果参数是异常类型,会隐式使用无参方式调用异常的构造器初始化一个异常实例:

raise ValueError  # shorthand for &#39;raise ValueError()&#39;
ログイン後にコピー
ログイン後にコピー

如果需要捕获异常但是不处理,一种更简单形式的raise语句允许重新抛出这个异常:

>>> try:
...     raise NameError(&#39;HiThere&#39;)
... except NameError:
...     print(&#39;An exception flew by!&#39;)
...     raise...
An exception flew by!Traceback (most recent call last):
  File "<stdin>", line 2, in <module>NameError: HiThere
ログイン後にコピー
ログイン後にコピー

8.5 User-defined Exception

程序中可以通过创建新异常类的方式提出自己的异常(参见Classes获取Python类的更多信息)。异常必须直接或者间接继承自Exception类。

自定义异常类拥有其他类的功能,但通常需要保持其简洁性,只提供几个供异常处理程序提取错误信息的属性。需要创建一个抛出若干不同错误的模块时,比较好的实践是,为定义在这个模块中的异常创建父类,由子类创建对应不同错误的具体异常:

class Error(Exception):"""Base class for exceptions in this module."""passclass 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 = expressionself.message = messageclass TransitionError(Error):"""Raised when an operation attempts a state transition that&#39;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 = previousself.next = nextself.message = message
ログイン後にコピー

与标准异常类类似,大多数异常的名字都以"Error"结尾。

许多标准模块都定义了自己的异常,这些异常对应模块中定义的函数中可能发生的错误。更多信息参考Classes。

8.6 Defining Clean-up Actions

try语句有可选的在任何情况下都会执行的子句,可用于定义清理动作。例如:

>>> try:
...     raise KeyboardInterrupt... finally:
...     print(&#39;Goodbye, world!&#39;)
...
Goodbye, world!KeyboardInterruptTraceback (most recent call last):
  File "<stdin>", line 2, in <module>
ログイン後にコピー

无论是否有异常发生,finally子句在离开try语句之前总是会执行。当try子句中有异常发生并且没有被except子句处理(或者异常发生在except子句或else子句),finally子句执行之后,这些异常会重新抛出。当try语句的其他子句通过break, continue或者return语句离开时,finally子句也会执行。以下是较为复杂的示例:

>>> 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.0executing 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 <module>
  File "<stdin>", line 3, in divideTypeError: unsupported operand type(s) for /: &#39;str&#39; and &#39;str&#39;
ログイン後にコピー

正如所见的那样,finally子句在任何情况下都会执行。两个字符串相除产生的TypeError异常没有被except子句处理,因此在finally子句执行完毕之后被重新抛出。

在实践应用中,finally子句用来释放外部资源(比如文件和网络连接),不论资源的使用是否成功。

8.7 Predefined Clean-up Actions

一些对象定义了标准的清理动作,当不再需要这些对象时,会执行清理动作,而不论使用对象的操作是否成功。以下示例读取文件并打印内容到显示器:

for line in open("myfile.txt"):print(line, end="")
ログイン後にコピー

这段代码的问题是:当代码执行完毕后,文件会保留打开状态一段不确定的时间。这在简单的脚本中不是什么大问题,但是在大型的应用程序中会出问题。with语句使得像文件一样的对象可以被立即准确回收。

with open("myfile.txt") as f:for line in f:print(line, end="")
ログイン後にコピー

语句执行后,即使在执行代码时遇到问题,文件f总是会被关闭。像文件一样提供预定义清理动作的对象会在其说明文档中指示这点。

以上がPython の 2 つのエラー タイプの紹介の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート