Syntax errors, also known as parsing errors, are perhaps the most common kind of complaint you get while you are still learning Python:html
语法错误,一样也称为句法分析错误,当你正在学习Python的过程当中,多是你抱怨最多的问题。python
>>> while True print('Hello world') File "<stdin>", line 1, in ? while True print('Hello world') ^ SyntaxError: invalid syntax
The parser repeats the offending line and displays a little ‘arrow’ pointing at the earliest point in the line where the error was detected. The error is caused by (or at least detected at) the token preceding the arrow: in the example, the error is detected at the function print(), since a colon (':') is missing before it. File name and line number are printed so you know where to look in case the input came from a script.程序员
语法分析器会重写出错的语句,并用一个向上的箭头指向错误被检查到的地方。在这个例子中,错误是因为在print()函数前缺乏冒号:形成的。文件名和行号也打印出来,所以你能够将错误输出到一个脚本中,方便定位问题。express
Even if a statement or expression is syntactically correct, it may cause an error when an attempt is made to execute it. Errors detected during execution are called exceptions and are not unconditionally fatal: you will soon learn how to handle them in Python programs. Most exceptions are not handled by programs, however, and result in error messages as shown here:app
即便语句或者表达式在语法上是正确的,执行的时候也可能出错。在程序运行期间出现致命错误或者程序调用异常时会进行错误检测:你将会学习到在Python程序中如何处理它们。许多异常程序是不会手动处理的:less
>>> 10 * (1/0) Traceback (most recent call last): File "<stdin>", line 1, in ? ZeroDivisionError: division by zero >>> 4 + spam*3 Traceback (most recent call last): File "<stdin>", line 1, in ? NameError: name 'spam' is not defined >>> '2' + 2 Traceback (most recent call last): File "<stdin>", line 1, in ? TypeError: Can't convert 'int' object to str implicitly
The last line of the error message indicates what happened. Exceptions come in different types, and the type is printed as part of the message: the types in the example are ZeroDivisionError, NameError and TypeError. The string printed as the exception type is the name of the built-in exception that occurred. This is true for all built-in exceptions, but need not be true for user-defined exceptions (although it is a useful convention). Standard exception names are built-in identifiers (not reserved keywords).ide
错误消息的最后一行显示发生了什么状况。异常有不少类型,并做为消息的一部分打印出来:在这个例子中,异常类型有ZeroDivisionError,NameError和TypeError。这些异常名字是Python内置的。用户也能够自定义异常类型。函数
The rest of the line provides detail based on the type of exception and what caused it.oop
错误消息的其余部分提供了引起异常的细节状况。学习
The preceding part of the error message shows the context where the exception happened, in the form of a stack traceback. In general it contains a stack traceback listing source lines; however, it will not display lines read from standard input.
错误消息的前面应该会指明异常发生的上下文,例如指出堆栈信息。通常状况下,它应该包含源码级别的堆栈信息;可是上面的例子是从标准输入设备中读取的代码,所以没有显示堆栈信息。
It is possible to write programs that handle selected exceptions. Look at the following example, which asks the user for input until a valid integer has been entered, but allows the user to interrupt the program (using Control-C or whatever the operating system supports); note that a user-generated interruption is signalled by raising the KeyboardInterrupt exception.
固然,咱们能够在程序中选择性的处理须要处理的异常。看下面的例子,请求用户的输入直到输入合法的整数值,可是也容许用户打断程序的运行(使用Control-C或者Control-Z);注意,用户触发的打断将会触发KeyboardInterrupt异常。
>>> while True: ... try: ... x = int(input("Please enter a number: ")) ... break ... except ValueError: ... print("Oops! That was no valid number. Try again...") ...
The try statement works as follows.
try语句工做机制:
A try statement may have more than one except clause, to specify handlers for different exceptions. At most one handler will be executed. Handlers only handle exceptions that occur in the corresponding try clause, not in other handlers of the same try statement. An except clause may name multiple exceptions as a parenthesized tuple, for example:
一个try语句有可能不止一个except语句块,能够为不一样的异常指定处理程序。但至多只有一个处理程序会执行。处理程序仅仅只处理try语句中相应的异常类型,而不会处理同一个try语句的其余异常。一个except语句块能够包含多个异常类型,例如:
... except (RuntimeError, TypeError, NameError): ... pass
The last except clause may omit the exception name(s), to serve as a wildcard. Use this with extreme caution, since it is easy to mask a real programming error in this way! It can also be used to print an error message and then re-raise the exception (allowing a caller to handle the exception as well):
try-except的最后一个except语句块能够省略异常的名字,来做为一个通配符。使用这种异常块要很是的当心,由于这种方式很容易掩盖程序真实的错误!它也可以先打印错误消息,并引起异常(容许调用函数来处理异常)。
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
The try ... except statement has an optional else clause, which, when present, must follow all except clauses. It is useful for code that must be executed if the try clause does not raise an exception. For example:
try...except语句有个可选择的else语句块,它必须跟随在全部的except语句块以后。它的做用是,若是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()
The use of the else clause is better than adding additional code to the try clause because it avoids accidentally catching an exception that wasn’t raised by the code being protected by the try ... except statement.
使用else语句块要比在try语句中增长额外的语句更好,由于它避免了意外的异常捕捉,这这个异常可能并非try...excepty语句中要捕捉的。
When an exception occurs, it may have an associated value, also known as the exception’s argument. The presence and type of the argument depend on the exception type.
当发生异常时,它可能有个关联值,也叫作异常的参数。这个参数的类型以及是否有这个参数取决于异常类型。
The except clause may specify a variable after the exception name. The variable is bound to an exception instance with the arguments stored in instance.args. For convenience, the exception instance defines __str__() so the arguments can be printed directly without having to reference .args. One may also instantiate an exception first before raising it and add any attributes to it as desired.
except语句块能够在异常名字的后面指定一个变量。这个变量绑定了该异常的实例,而且异常的参数存储在instance.args。为了方便,异常实例定义了一个__str()__函数,所以参数能够直接打印而没必要引用.args。可能有人想在抛出异常前先初始化异常实例,给该异常增长一些所指望的属性。
>>> try: ... raise Exception('spam', 'eggs') ... 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('x =', x) ... print('y =', y) ... <class 'Exception'> ('spam', 'eggs') ('spam', 'eggs') x = spam y = eggs
If an exception has arguments, they are printed as the last part (‘detail’) of the message for unhandled exceptions.
若是一个异常带有参数,这个异常若是没有被处理,那么它的这些参数会在错误消息的最后面打印出来。
Exception handlers don’t just handle exceptions if they occur immediately in the try clause, but also if they occur inside functions that are called (even indirectly) in the try clause. For example:
异常处理程序不只仅只处理在try语句块中出现的异常,并且还能够处理在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
The raise statement allows the programmer to force a specified exception to occur. For example:
raise语句运行程序员迫使指定的异常发生。例如:
>>> raise NameError('HiThere') Traceback (most recent call last): File "<stdin>", line 1, in ? NameError: HiThere
The sole argument to raise indicates the exception to be raised. This must be either an exception instance or an exception class (a class that derives from Exception).
raise惟一的参数代表了什么异常被抛出。这个参数必须是异常实例或者是Exception类及子类。
If you need to determine whether an exception was raised but don’t intend to handle it, a simpler form of the raise statement allows you to re-raise the 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
Programs may name their own exceptions by creating a new exception class (see Classes for more about Python classes). Exceptions should typically be derived from the Exception class, either directly or indirectly. For example:
程序者可能但愿本身能建立一个新的异常类。那么这个异常类必须直接或间接的继承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!'
In this example, the default __init__() of Exception has been overridden. The new behavior simply creates the value attribute. This replaces the default behavior of creating the args attribute.
在这个例子中,Exception类默认的__init__()函数被覆盖了。新的__init__()函数仅仅建立一个value属性。这个替换了args属性的默认行为。
Exception classes can be defined which do anything any other class can do, but are usually kept simple, often only offering a number of attributes that allow information about the error to be extracted by handlers for the exception. When creating a module that can raise several distinct errors, a common practice is to create a base class for exceptions defined by that module, and subclass that to create specific exception classes for different error conditions:
一个异常类能够像其余类同样作任何事情,可是一般都是保持简单的形式,一般是仅仅提供一些属性来关联错误信息,并当处理程序引起异常时调用。当建立一个模块能够引起几种不一样的错误时,一个广泛的作法是建立一个基类,而后子类处理不一样的异常错误类型。
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
Most exceptions are defined with names that end in “Error,” similar to the naming of the standard exceptions.
大多数自定义的异常类的名字都是以"Error"结尾,这相似于标准异常类的风格。
Many standard modules define their own exceptions to report errors that may occur in functions they define. More information on classes is presented in chapter Classes.
许多标准的模块都定义了他们本身的异常来报告错误。关于类的描述,请查阅Classes章节。
The try statement has another optional clause which is intended to define clean-up actions that must be executed under all circumstances. For example:
try语句还有另外一个可选的子块,这个子块主要是用来作一些清理工做。
>>> try: ... raise KeyboardInterrupt ... finally: ... print('Goodbye, world!') ... Goodbye, world! KeyboardInterrupt
A finally clause is always executed before leaving the try statement, whether an exception has occurred or not. When an exception has occurred in the try clause and has not been handled by an except clause (or it has occurred in a except or else clause), it is re-raised after the finally clause has been executed. The finally clause is also executed “on the way out” when any other clause of the try statement is left via a break, continue or return statement. A more complicated example:
在例子try语句以前,finally子块老是必须执行,不论是否发生异常。当一个异常在try语句块中引起而没有except子块处理,它会在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.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'
As you can see, the finally clause is executed in any event. The TypeError raised by dividing two strings is not handled by the except clause and therefore re-raised after the finally clause has been executed.
正如你所看见的,finally子块老是会执行。两个字符串相除引起的TypeError异常没有被except子块处理,所以,在finally子块执行完后从新抛出。
In real world applications, the finally clause is useful for releasing external resources (such as files or network connections), regardless of whether the use of the resource was successful.
在真实的程序世界中,fianlly子块一般是用来释放一下额外的资源,无论资源是否被使用成功。
Some objects define standard clean-up actions to be undertaken when the object is no longer needed, regardless of whether or not the operation using the object succeeded or failed. Look at the following example, which tries to open a file and print its contents to the screen.
有些对象定义了标准的清理操做。当对象再也不须要使用的时候,就会自动清理资源,无论对象调用的操做是否成功。看下面的例子,尝试打开一个文件,并将内容输出到屏幕上。
for line in open("myfile.txt"): print(line, end="")
The problem with this code is that it leaves the file open for an indeterminate amount of time after this part of the code has finished executing. This is not an issue in simple scripts, but can be a problem for larger applications. The with statement allows objects like files to be used in a way that ensures they are always cleaned up promptly and correctly.
这段代码的问题是:当这部分的代码执行完毕后,文件一直处于打开的状态。这在一个简单的脚本中不会有什么问题,可是在一个大的程序中可能会出现问题。with语句容许相似于文件对象的对象在使用后,确保他们老是合适的、正确的被清理掉。
with open("myfile.txt") as f: for line in f: print(line, end="")
After the statement is executed, the file f is always closed, even if a problem was encountered while processing the lines. Objects which, like files, provide predefined clean-up actions will indicate this in their documentation.
当语句执行后,f对象老是会关闭,既使在处理文件的过程当中出现了问题。相似于文件的对象他们提供了提早清理资源的操做,这些内容能够参阅这些对象相关的文档。