Until now error messages haven't been more than mentioned, but if you have tried out the examples you have probably seen some. There are (at least) two distinguishable kinds of errors: syntax errors and exceptions.
至今為止還沒有進(jìn)一步的談?wù)撨^錯誤信息,不過在你已經(jīng)試驗(yàn)過的那些例子中,可能已經(jīng)遇到過一些。Python 中(至少)有兩種錯誤:語法錯誤和異常( syntax errorsand exceptions )。
Syntax errors, also known as parsing errors, are perhaps the most common kind of complaint you get while you are still learning Python:
語法錯誤,也稱作解析錯誤,可能是學(xué)習(xí) 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 keyword 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.
解析器會重復(fù)出錯的行,并在行中最早發(fā)現(xiàn)的錯誤位置上顯示一個小箭頭。錯誤(至少是被檢測到的)就發(fā)生在箭頭指向的位置。示例中的錯誤表現(xiàn)在關(guān)鍵字print 上,因?yàn)樵谒吧倭艘粋冒號( ":")。同時也會顯示文件名和行號,這樣你就可以知道錯誤來自哪個腳本,什么位置。
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:
即使是在語法上完全正確的語句,嘗試執(zhí)行它的時候,也有可能會發(fā)生錯誤。在程序運(yùn)行中檢測出的錯誤稱之為異常,它通常不會導(dǎo)致致命的問題,你很快就會學(xué)到如何在 Python 程序中控制它們。大多數(shù)異常不會由程序處理,而是顯示一個錯誤信息:
>>> 10 * (1/0) Traceback (most recent call last): File "<stdin>", line 1, in ? ZeroDivisionError: integer division or modulo 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: cannot concatenate 'str' and 'int' objects
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).
錯誤信息的最后一行指出發(fā)生了什么錯誤。異常也有不同的類型,異常類型做為錯誤信息的一部分顯示出來:示例中的異常分別為 零除錯誤( ZeroDivisionError ) ,命名錯誤( NameError) 和 類型錯誤(TypeError)。打印錯誤信息時,異常的類型作為異常的內(nèi)置名顯示。對于所有的內(nèi)置異常都是如此,不過用戶自定義異常就不一定了(盡管這是一個很有用的約定)。標(biāo)準(zhǔn)異常名是內(nèi)置的標(biāo)識(沒有保留關(guān)鍵字)。
The rest of the line is a detail whose interpretation depends on the exception type; its meaning is dependent on the exception type.
這一行后一部分是關(guān)于該異常類型的詳細(xì)說明,這意味著它的內(nèi)容依賴于異常類型。
The preceding part of the error message shows the context where the exception happened, in the form of a stack backtrace. In general it contains a stack backtrace listing source lines; however, it will not display lines read from standard input.
錯誤信息的前半部分以堆棧的形式列出異常發(fā)生的位置。通常在堆棧中列出了源代碼行,然而,來自標(biāo)準(zhǔn)輸入的源碼不會顯示出來。
The Python Library Reference lists the built-in exceptions and their meanings.
Python 庫參考手冊列出了內(nèi)置異常和它們的含義。
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.
通過編程可以處理指定的異常。以下的例子重復(fù)要求用戶輸入一個值,直到用戶輸入的是一個合法的整數(shù)為止。不過這個程序允許用戶中斷程序(使用Control-C 或者其它操作系統(tǒng)支持的方法)。需要注意的是用戶發(fā)出的中斷會引發(fā)一個KeyboardInterrupt 異常。
>>> while True: ... try: ... x = int(raw_input("Please enter a number: ")) ... break ... except ValueError: ... print "Oops! That was no valid number. Try again..." ...
The try statement works as follows.
try 語句按如下方式工作:
首先,執(zhí)行 try 子句(在 try 和 except 關(guān)鍵字之間的部分)。
如果沒有異常發(fā)生, except 子句 在 try 語句執(zhí)行完畢后就被忽略了。
如果在 try 子句執(zhí)行過程中發(fā)生了異常,那么該子句其余的部分就會被忽略。如果異常匹配于 except 關(guān)鍵字后面指定的異常類型,就執(zhí)行對應(yīng)的except子句,忽略try子句的其它部分。然后繼續(xù)執(zhí)行try語句之后的代碼。
如果發(fā)生了一個異常,在 except 子句中沒有與之匹配的分支,它就會傳遞到上一級 try 語句中。如果最終仍找不到對應(yīng)的處理語句,它就成為一個未處理異常,終止程序運(yùn)行,顯示提示信息。
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 list, for example:
一個 try 語句可能包含多個 except 子句,分別指定處理不同的異常。至多只會有一個分支被執(zhí)行。異常處理程序只會處理對應(yīng)的 try 子句中發(fā)生的異常,在同一個 try 語句中,其他子句中發(fā)生的異常則不作處理。一個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):
最后一個 except 子句可以省略異常名,把它當(dāng)做一個通配項(xiàng)使用。一定要慎用這種方法,因?yàn)樗芸赡軙帘蔚粽嬲某绦蝈e誤,使人無法發(fā)現(xiàn)!它也可以用于打印一行錯誤信息,然后重新拋出異常(可以使調(diào)用者更好的處理異常)。
import sys try: f = open('myfile.txt') s = f.readline() i = int(s.strip()) except IOError, (errno, strerror): print "I/O error(%s): %s" % (errno, strerror) 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 子句, 該子句只能出現(xiàn)在所有 except 子句之后。當(dāng) try 語句沒有拋出異常時,需要執(zhí)行一些代碼,可以使用這個子句。例如:
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 子句中附加代碼要好,因?yàn)檫@樣可以避免 try ...
keywordexcept 意外的截獲本來不屬于它們保護(hù)的那些代碼拋出的異常。
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.
發(fā)生異常時,可能會有一個附屬值,作為異常的參數(shù)存在。這個參數(shù)是否存在、是什么類型,依賴于異常的類型。
The except clause may specify a variable after the exception name (or list).
The variable is bound to an exception instance with the arguments stored
in instance.args
. For convenience, the exception instance
defines __getitem__ and __str__ so the arguments can
be accessed or printed directly without having to reference .args
.
在異常名(列表)之后,也可以為 except 子句指定一個變量。這個變量綁定于一個異常實(shí)例,它存儲在 instance.args
的參數(shù)中。為了方便起見,異常實(shí)例定義了 __getitem__ 和 __str__,這樣就可以直接訪問過打印參數(shù)而不必引用 .args
。
>>> try: ... raise Exception('spam', 'eggs') ... except Exception, inst: ... print type(inst) # the exception instance ... print inst.args # arguments stored in .args ... print inst # __str__ allows args to printed directly ... x, y = inst # __getitem__ allows args to be unpacked directly ... print 'x =', x ... print 'y =', y ... <type 'instance'> ('spam', 'eggs') ('spam', 'eggs') x = spam y = eggs
If an exception has an argument, it is printed as the last part (`detail') of the message for unhandled exceptions.
對于未處理的異常,如果它有一個參數(shù),那做就會作為錯誤信息的最后一部分(“明細(xì)”)打印出來。
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:
異常處理句柄不止可以處理直接發(fā)生在 try 子句中的異常,即使是其中(甚至是間接)調(diào)用的函數(shù),發(fā)生了異常,也一樣可以處理。例如:
>>> def this_fails(): ... x = 1/0 ... >>> try: ... this_fails() ... except ZeroDivisionError, detail: ... print 'Handling run-time error:', detail ... Handling run-time error: integer division or modulo
The raise statement allows the programmer to force a specified exception to occur. For example:
在發(fā)生了特定的異常時,程序員可以用 raise 語句強(qiáng)制拋出異常。例如:
>>> raise NameError, 'HiThere' Traceback (most recent call last): File "<stdin>", line 1, in ? NameError: HiThere
The first argument to raise names the exception to be raised. The optional second argument specifies the exception's argument.
第一個參數(shù)指定了所拋出異常的名稱,第二個指定了異常的參數(shù)。
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. Exceptions should typically be derived from the Exception class, either directly or indirectly. For example:
在程序中可以通過創(chuàng)建新的異常類型來命名自己的異常。異常類通常應(yīng)該直接或間接的從 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, 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 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 which 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:
異常類中可以定義任何其它類中可以定義的東西,但是通常為了保持簡單,只在其中加入幾個屬性信息,以供異常處理句柄提取。如果一個新創(chuàng)建的模塊中需要拋出幾種不同的錯誤時,一個通常的作法是為該模塊定義一個異常基類,然后針對不同的錯誤類型派生出對應(yīng)的異常子類。
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.
與標(biāo)準(zhǔn)異常相似,大多數(shù)異常的命名都以“Error”結(jié)尾。
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
很多標(biāo)準(zhǔn)模塊中都定義了自己的異常,用以報(bào)告在他們所定義的函數(shù)中可能發(fā)生的錯誤。關(guān)于類的進(jìn)一步信息請參見第 9 章
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 語句還有另一個可選的子句,目的在于定義在任何情況下都一定要執(zhí)行的功能。例如:
>>> try: ... raise KeyboardInterrupt ... finally: ... print 'Goodbye, world!' ... Goodbye, world! Traceback (most recent call last): File "<stdin>", line 2, in ? KeyboardInterrupt
A finally clause is executed whether or not an exception has occurred in the try clause. When an exception has occurred, it is re-raised after the finally clause is executed. The finally clause is also executed ``on the way out'' when the try statement is left via a break or return statement.
不管try子句中有沒有發(fā)生異常, finally 子句都一定會被執(zhí)行。如果發(fā)生異常,在 finally 子句執(zhí)行完后它會被重新拋出。 try 子句經(jīng)由 break 或 return 退出也一樣會執(zhí)行 finally 子句。
The code in the finally clause is useful for releasing external resources (such as files or network connections), regardless of whether or not the use of the resource was successful.
在 finally 子句中的代碼用于釋放外部資源(例如文件或網(wǎng)絡(luò)連接),不管這些資源是否已經(jīng)成功利用。
A try statement must either have one or more except clauses or one finally clause, but not both.
在 try 語句中可以使用若干個 except 子句或一個 finally 子句,但兩者不能共存。
譯者:劉鑫(march.liu AT gmail DOT com) 由:limodou轉(zhuǎn)(limodou AT gmail DOT com) CHM 文件制作:Colin.Wang 2007年9月