2016-01-11 66 views
5

我嘗試編寫一些代碼來捕獲斷開的管道錯誤。代碼應該在Python 2.x和Python 3.x中運行。在Python 2和Python 3中捕獲斷開的管道

在Python 2.xa破裂的管道由socket.error

socket.error: [Errno 32] Broken pipe 

這是在Python 3.x的改變 - 表示一個破碎管現在是一個BrokenPipeError

BrokenPipeError: [Errno 32] Broken pipe 

另外的語法異常處理已經改變了一些(見https://stackoverflow.com/a/34463112/263589),所以我需要做的是這樣的:

try: 
    do_something() 
except BrokenPipeError as e: # implies Python 3.x 
    resolve_for_python2() 
except socket.error as e: 
    if sys.version_info[0] == 2: # this is necessary, as in Python >=3.3 
           # socket.error is an alias of OSError 
           # https://docs.python.org/3/library/socket.html#socket.error 
     resolve_for_python3() 
    else: 
     raise 

還有(至少)一個剩餘的問題:在Python 2.x中沒有BrokenPipeError,所以無論何時在do_something()中發生異常,Python 2.x都會拋出另一個異常並抱怨它不知道BrokenPipeError。由於socket.error在Python 3.x中被棄用,在不久的將來,Python 3.x中可能會出現類似的問題。

我該怎麼做才能讓這段代碼在Python 2.x和Python 3.x中運行?

+0

看看http://python-future.org/compatible_idioms.html,它們顯示異常處理。 – MKesper

+1

http://newbebweb.blogspot.in/2012/02/python-head-ioerror-errno-32-broken.html這裏是 –

+0

謝謝!但http://python-future.org/compatible_idioms.html#catching-exceptions沒有解釋如何捕獲Python 2或Python 3中不存在的異常,但在其他版本中是強制性的。 – speendo

回答

3

如果所有你關心的是破管錯誤,那麼你可能想趕上socket.error並簡單地檢查它是否確實是一個破管錯誤。

您可以使用異常的errno屬性來實現,該屬性存在於Python 2和Python 3中,這意味着,您不需要不同的Python 2與3邏輯(我認爲其意圖有點不同更清晰的這種方式):

import socket 
import errno 


try: 
    do_something() 
except socket.error as e: 
    if e.errno != errno.EPIPE: 
     # Not a broken pipe 
     raise 
    do_something_about_the_broken_pipe() 

如果你關心比破損的管道多,thefourtheye的回答是適當的,地道。

+0

謝謝!它讓我感到有些擔心,因爲在Python 3中不推薦使用'socket.error'。所以如果我更新我的Python 3解釋器,那麼在(將來的)將來可能會有另一個問題... – speendo

+1

@speendo有幾十個引用Python標準庫本身的''socket.error' * *。它已被棄用,當然,但它不會消失。刪除'socket.error'將是一個毫無意義的重大改變,這是Python核心開發人員公開表示他們將來會避免的。如果它確實最終被刪除(幾十年後?),那麼這個錯誤對於識別和修復來說是微不足道的,在那一刻,你可能不會再支持Python 2了。 –

+0

有道理.... – speendo

1

您可以嘗試使用BrokenPipeError,如果它拋出一個NameError,然後回落到socket.error,這樣

import socket 
try: 
    expected_error = BrokenPipeError 
except NameError: 
    expected_error = socket.error 

,然後用它像這樣

try: 
    1 == 2 
except expected_error as ex: 
    # Handle the actual exception here