<span id="7ztzv"></span>
<sub id="7ztzv"></sub>

<span id="7ztzv"></span><form id="7ztzv"></form>

<span id="7ztzv"></span>

        <address id="7ztzv"></address>

            第 6 章 異常和文件處理

            在本章中,將研究異常、文件對象、for 循環、ossys 模塊等內容。如果你已經在其它編程語言中使用過異常,你可以簡單看看第一部分來了解 Python 的語法。但是本章其它的內容仍需仔細研讀。

            6.1. 異常處理

            與許多面向對象語言一樣,Python 具有異常處理,通過使用 try...except 塊來實現。

            注意
            Python 使用 try...except 來處理異常,使用 raise 來引發異常。JavaC++ 使用 try...catch 來處理異常,使用 throw 來引發異常。

            異常在 Python 中無處不在;實際上在標準 Python 庫中的每個模塊都使用了它們,并且 Python 自已會在許多不同的情況下引發它們。在整本書中你已經再三看到它們了。

            在這些情況下,我們都在簡單地使用 Python IDE:一個錯誤發生了,異常被打印出來 (取決于你的 IDE,可能會有意地以一種刺眼的紅色形式表示),這便是。這叫做未處理 異常;當異常被引發時,沒有代碼來明確地關注和處理它,所以異常被傳給置在 Python 中的缺省的處理,它會輸出一些調試信息并且終止運行。在 IDE 中,這不是什么大事,但是如果發生在你真正的 Python 程序運行的時候,整個程序將會終止。

            然而,一個異常不一定會引起程序的完全崩潰。當異常引發時,可以被處理 掉。有時候一個異常實際是因為代碼中的 bug (比如使用一個不存在的變量),但是許多時候,一個異常是可以預見的。如果你打開一個文件,它可能不存在。如果你連接一個數據庫,它可能不可連接或沒有訪問所需的正確的安全證書。如果知道一行代碼可能會引發異常,你應該使用一個 try...except 塊來處理異常。

            例 6.1. 打開一個不存在的文件

            >>> fsock = open("/notthere", "r")      1
            Traceback (innermost last):
              File "<interactive input>", line 1, in ?
            IOError: [Errno 2] No such file or directory: '/notthere'
            >>> try:
            ...     fsock = open("/notthere")       2
            ... except IOError:                     3
            ...     print "The file does not exist, exiting gracefully"
            ... print "This line will always print" 4
            The file does not exist, exiting gracefully
            This line will always print
            1 使用內置 open 函數,我們可以試著打開一個文件來讀取 (在下一節有關于 open 的更多內容)。但是那個文件不存在,所以這樣就引發 IOError 異常。因為我們沒有提供任何顯式的對 IOError 異常的檢查,Python 僅僅打印出某個關于發生了什么的調試信息,然后終止。
            2 我們試圖打開同樣不存在的文件,但是這次我們在一個 try...except 內來執行它。
            3 open 方法引發 IOError 異常時,我們已經準備好處理它了。except IOError: 行捕捉異常,接著執行我們自已的代碼塊,這個代碼塊在本例中只是打印出更令人愉快的錯誤信息。
            4 一旦異常被處理了,處理通常在 try...except 塊之后的第一行繼續進行。注意這一行將總是打印出來,無論異常是否發生。如果在你的根目錄下確實有一個叫 notthere 的文件,對 open 的調用將成功,except 子句將忽略,并且最后一行仍將執行。

            異常可能看上去不友好 (畢竟,如果你不捕捉異常,整個程序將崩潰),但是考慮一下別的方法。你該不會希望獲得一個指向不存在的文件的對象吧?不管怎么樣你都得檢查它的有效性,而且如果你忘記了,你的程序將會在下面某個地方給出奇怪的錯誤,這樣你將不得不追溯到源程序。我確信你做過這種事;這可并不有趣。使用異常,一發生錯誤,你就可以在問題的源頭通過標準的方法來處理它們。

            6.1.1. 為其他用途使用異常

            除了處理實際的錯誤條件之外,對于異常還有許多其它的用處。在標準 Python 庫中一個普通的用法就是試著導入一個模塊,然后檢查是否它能使用。導入一個并不存在的模塊將引發一個 ImportError 異常。你可以使用這種方法來定義多級別的功能――依靠在運行時哪個模塊是有效的,或支持多種平臺 (即平臺特定代碼被分離到不同的模塊中)。

            你也能通過創建一個從內置的 Exception 類繼承的類定義你自己的異常,然后使用 raise 命令引發你的異常。如果你對此感興趣,請看進一步閱讀的部分。

            下面的例子演示了如何使用異常支持特定平臺功能。代碼來自 getpass 模塊,一個從用戶獲得口令的封裝模塊。獲得口令在 UNIX、Windows 和 Mac OS 平臺上的實現是不同的,但是這個代碼封裝了所有的不同之處。

            例 6.2. 支持特定平臺功能

              # Bind the name getpass to the appropriate function
              try:
                  import termios, TERMIOS                     1
              except ImportError:
                  try:
                      import msvcrt                           2
                  except ImportError:
                      try:
                          from EasyDialogs import AskPassword 3
                      except ImportError:
                          getpass = default_getpass           4
                      else:                                   5
                          getpass = AskPassword
                  else:
                      getpass = win_getpass
              else:
                  getpass = unix_getpass
            1 termiosUNIX 獨有的一個模塊,它提供了對于輸入終端的底層控制。如果這個模塊無效 (因為它不在你的系統上,或你的系統不支持它),則導入失敗,Python 引發我們捕捉的 ImportError 異常。
            2 OK,我們沒有 termios,所以讓我們試試 msvcrt,它是 Windows 獨有的一個模塊,可以提供在 Microsoft Visual C++ 運行服務中的許多有用的函數的一個API。如果導入失敗,Python 會引發我們捕捉的 ImportError 異常。
            3 如果前兩個不能工作,我們試著從 EasyDialogs 導入一個函數,它是 Mac OS 獨有的一個模塊,提供了各種各樣類型的彈出對話框。再一次,如果導入失敗,Python 會引發一個我們捕捉的 ImportError 異常。
            4 這些平臺特定的模塊沒有一個有效 (有可能,因為 Python 已經移植到了許多不同的平臺上了),所以我們需要回頭使用一個缺省口令輸入函數 (這個函數定義在 getpass 模塊中的別的地方)。注意我們在這里所做的:我們將函數 default_getpass 賦給變量 getpass。如果你讀了官方 getpass 文檔,它會告訴你 getpass 模塊定義了一個 getpass 函數。它是這樣做的:通過綁定 getpass 到正確的函數來適應你的平臺。然后當你調用 getpass 函數時,你實際上調用了平臺特定的函數,是這段代碼已經為你設置好的。你不需要知道或關心你的代碼正運行在何種平臺上;只要調用 getpass,則它總能正確處理。
            5 一個 try...except 塊可以有一條 else 子句,就像 if 語句。如果在 try 塊中沒有異常引發,然后 else 子句被執行。在本例中,那就意味著如果 from EasyDialogs import AskPassword 導入可工作,所以我們應該綁定 getpassAskPassword 函數。其它每個 try...except 塊有著相似的 else 子句,當我們發現一個 import 可用時,就綁定 getpass 到適合的函數。

            進一步閱讀

            <span id="7ztzv"></span>
            <sub id="7ztzv"></sub>

            <span id="7ztzv"></span><form id="7ztzv"></form>

            <span id="7ztzv"></span>

                  <address id="7ztzv"></address>

                      亚洲欧美在线