Introduction to two error types in Python

零下一度
Release: 2017-07-23 14:06:03
Original
3588 people have browsed it

I haven’t introduced much about error messages so far, but they have been used in some examples. Python has at least two types of errors: Syntax errors and Exceptions

8.1 Syntax Errors

Syntax errors, also called parsing errors, are Python A common complaint among beginners.

>>> while True print('Hello world')
  File "<stdin>", line 1while True print(&#39;Hello world&#39;)                   ^SyntaxError: invalid syntax
Copy after login

The Python parser repeatedly prints the error line and displays a small arrow pointing to the position in the error line where the error was first detected. The error is caused by the statement before the arrow (at least that's what is detected): In the above example, the error is detected in the print() function because of the colon :## before it # is missing. The file name and line number are also printed, making it easier to locate problems when the program comes from a script.

8.2 Exceptions

Even if the statement or expression is grammatically correct, errors may occur during execution. Problems detected during execution are called

Exceptions. Exceptions are not absolutely fatal errors: Next, we will introduce how to handle exceptions in Python. However, most exceptions will not be handled by the program, and they will eventually become error messages, as shown below:

>>> 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
Copy after login
The last line of the error message indicates what happened. There are different types of exceptions, and the types are also printed as part of the error message: the types in the above example are Division by ZeroException

ZeroDivisionError, NameExceptionNameError and TypeExceptionTypeError. The string printed as the exception type is the name of the built-in exception. This is true for all built-in exceptions, and although this convention is useful, not all user-defined exceptions will adhere to it. Standard exception names are built-in identifiers (not reserved words).

The remaining lines show detailed information based on the exception type and the reason why the exception occurred.

The previous error information displays the context information of the exception in the form of stack traceback. Normally the source code lines are listed in the stack traceback; however, when the program is reading from standard input, the lines are not displayed.

Built-in exceptions lists all built-in exceptions and their meanings.

8.3 Handling Exceptions

Python programs allow handling of specified exceptions. The following program requires the user to loop input until the input is a valid integer, but the program can also be interrupted (using

Control-C or other means supported by the operating system); note that user-induced interruptions will throw a KeyboardInterrupt exception.

while True:try:
        x = int(input("Please enter a number: "))breakexcept ValueError:print("Oops!  That was no valid number.  Try again...")
Copy after login

tryThe execution order of statements is:

  • First, execute the steps between

    try and The try clause between except

  • If no exception occurs, skip the

    except clause , tryStatement execution completed

  • If an exception occurs during the execution of the try clause, the remaining statements in the clause are skipped. Next, if the exception type thrown can match the exception after the keyword

    except, then the except clause is executed, and then the statement after the try statement continues.

  • If an exception occurs but no exception after except is matched, the exception is thrown to the outer

    try statement; if the exception cannot be handled, the exception becomes Unhandled exception, causing the program to terminate and print a message like the example above.

A

try statement can have multiple except clauses to specify handling methods for different exceptions. At most one except clause will be executed. The handler will only handle exceptions that occur in the corresponding try clause, and will not handle exceptions that occur in other handlers in the same try statement. An except clause can list multiple exceptions using a parenthesized tuple, like this:

... except (RuntimeError, TypeError, NameError):
...     pass
Copy after login

except The classes in the clause can match types that are Exceptions of its subclasses or its own type (but not the other way around, subclasses in the except clause will not match parent class exceptions). For example, the following code will print B, C, D in sequence:

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")
Copy after login
Note that if the above except clause is written in reverse (

except B comes first), then it will Print B, B, B - The first except clause match is triggered.

The last except clause can omit the exception name as a wildcard character. Because doing so can hide other real program errors, use it with caution. Can also be used to print error information and rethrow (allowing the caller to handle the exception):

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
Copy after login

try...except statement There is an optional else clause, which can only appear after all except clauses. If a section of code must be executed when the try clause does not throw an exception, it is useful to use the else clause (Translation Note: else clause will be return, break, continue skipped). For example:

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()
Copy after login

使用 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
Copy after login

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

异常处理程序不仅仅会处理即时发生在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
Copy after login

8.4 Raising Exceptions

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

>>> raise NameError(&#39;HiThere&#39;)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>NameError: HiThere
Copy after login

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

raise ValueError  # shorthand for &#39;raise ValueError()&#39;
Copy after login

如果需要捕获异常但是不处理,一种更简单形式的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
Copy after login

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
Copy after login

与标准异常类类似,大多数异常的名字都以"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>
Copy after login

无论是否有异常发生,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;
Copy after login

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

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

8.7 Predefined Clean-up Actions

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

for line in open("myfile.txt"):print(line, end="")
Copy after login

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

with open("myfile.txt") as f:for line in f:print(line, end="")
Copy after login

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

The above is the detailed content of Introduction to two error types in Python. For more information, please follow other related articles on the PHP Chinese website!

Related labels:
source:php.cn
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template