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對象老是會關閉,既使在處理文件的過程當中出現了問題。相似於文件的對象他們提供了提早清理資源的操做,這些內容能夠參閱這些對象相關的文檔。