2016-01-11 33 views
5

Tôi cố gắng viết một số mã để bắt lỗi hỏng ống. Mã nên chạy trong Python 2.x và Python 3.x.Bắt ống bị hỏng trong Python 2 và Python 3

Trong Python 2.xa ống vỡ được đại diện bởi một socket.error

socket.error: [Errno 32] Broken pipe 

này được thay đổi bằng Python 3.x - một đường ống bị hỏng bây giờ là một BrokenPipeError

BrokenPipeError: [Errno 32] Broken pipe 

Ngoài ra cú pháp của xử lý ngoại lệ đã thay đổi một chút (xem https://stackoverflow.com/a/34463112/263589) vì vậy những gì tôi cần làm sẽ là một cái gì đó như:

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 

Có (ít nhất) một vấn đề còn lại: Trong Python 2.x không có BrokenPipeError, vì vậy bất cứ khi nào có ngoại lệ trong do_something() Python 2.x sẽ ném một ngoại lệ khác và khiếu nại rằng nó không biết BrokenPipeError. Vì socket.error không còn được dùng trong Python 3.x, một vấn đề tương tự có thể phát sinh trong Python 3.x trong tương lai gần.

Tôi có thể làm gì để làm cho mã này chạy trong Python 2.x và Python 3.x?

+0

Hãy xem http://python-future.org/compatible_idioms.html, chúng hiển thị xử lý ngoại lệ. – MKesper

+1

http://newbebweb.blogspot.in/2012/02/python-head-ioerror-errno-32-broken.html đây là –

+0

Cảm ơn bạn! Nhưng http://python-future.org/compatible_idioms.html#catching-exceptions không giải thích cách bắt một ngoại lệ không tồn tại trong Python 2 hoặc Python 3 nhưng là bắt buộc trong phiên bản khác. – speendo

Trả lời

3

Nếu tất cả các bạn quan tâm là lỗi ống bị hỏng, sau đó bạn có thể muốn bắt socket.error và chỉ cần kiểm tra xem nó thực sự là một lỗi đường ống bị hỏng.

Bạn có thể làm như vậy bằng thuộc tính errno của ngoại lệ, có mặt trong cả Python 2 và Python 3, có nghĩa là bạn không cần Python 2 so với logic 3 (tôi cho rằng ý định là một chút rõ ràng hơn theo cách này):

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() 

Nếu bạn quan tâm đến nhiều hơn ống bị hỏng, câu trả lời thefourtheye là phù hợp và thành ngữ.

+0

Cảm ơn bạn! Nó lo lắng cho tôi một chút rằng 'socket.error' bị phản đối trong Python 3. Vì vậy, trong trường hợp tôi cập nhật trình thông dịch Python 3, có thể có một vấn đề khác trong tương lai (gần) ... – speendo

+1

@speendo có hàng tá tham chiếu đến 'socket.error' * trong thư viện chuẩn Python *. Nó không được chấp nhận, chắc chắn, nhưng nó không biến mất. Việc xóa 'socket.error' sẽ là một thay đổi đột phá, đó là điều mà các nhà phát triển cốt lõi của Python đã tuyên bố công khai họ sẽ tránh trong tương lai. Nếu nó đã bị xóa (trong vài thập niên ?!;)), lỗi sẽ không quan trọng để xác định và sửa chữa, và tại thời điểm đó, có thể bạn sẽ không hỗ trợ Python 2 nữa. –

+0

có ý nghĩa .... – speendo

1

Bạn có thể thử sử dụng BrokenPipeError và nếu nó ném một NameError, sau đó rơi trở lại socket.error, như thế này

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

Và sau đó sử dụng nó như thế này

try: 
    1 == 2 
except expected_error as ex: 
    # Handle the actual exception here 
Các vấn đề liên quan