Bắt nhiều ngoại lệ trong một dòng (ngoại trừ khối)


2757

Tôi biết rằng tôi có thể làm:

try:
    # do something that may fail
except:
    # do this if ANYTHING goes wrong

Tôi cũng có thể làm điều này:

try:
    # do something that may fail
except IDontLikeYouException:
    # say please
except YouAreTooShortException:
    # stand on a ladder

Nhưng nếu tôi muốn làm điều tương tự bên trong hai trường hợp ngoại lệ khác nhau, điều tốt nhất tôi có thể nghĩ ngay bây giờ là làm điều này:

try:
    # do something that may fail
except IDontLikeYouException:
    # say please
except YouAreBeingMeanException:
    # say please

Có cách nào để tôi có thể làm điều gì đó như thế này không (vì hành động cần thực hiện trong cả hai trường hợp ngoại lệ là say please):

try:
    # do something that may fail
except IDontLikeYouException, YouAreBeingMeanException:
    # say please

Bây giờ điều này thực sự sẽ không hoạt động, vì nó phù hợp với cú pháp cho:

try:
    # do something that may fail
except Exception, e:
    # say please

Vì vậy, nỗ lực của tôi để nắm bắt hai ngoại lệ khác biệt không chính xác đi qua.

Có cách nào để làm việc này không?


6
Lưu ý rằng trong Python 3, cái sau không còn là cú pháp hợp lệ.
gerrit

Câu trả lời:


3724

Từ Tài liệu Python :

Ví dụ, một mệnh đề ngoại lệ có thể đặt tên cho nhiều trường hợp ngoại lệ là một tuple được ngoặc đơn

except (IDontLikeYouException, YouAreBeingMeanException) as e:
    pass

Hoặc, chỉ dành cho Python 2:

except (IDontLikeYouException, YouAreBeingMeanException), e:
    pass

Việc tách ngoại lệ khỏi biến bằng dấu phẩy vẫn sẽ hoạt động trong Python 2.6 và 2.7, nhưng hiện không được dùng nữa và không hoạt động trong Python 3; bây giờ bạn nên sử dụng as.


9
Tôi đã thử nó ... với một list, và nó đã dẫn đến một TypeError. Có vẻ như các lỗi phải ở trong một tuplebắt để làm việc như mong đợi.
BallpointBen

4
Tại sao bạn đã từng sử dụng một danh sách khi bạn thấy rõ rằng nó được ghi lại rằng một tuple là cần thiết trong trường hợp này?
Mechanical_meat

6
Không rõ liệu "tuple ngoặc đơn" chỉ đơn thuần là cú pháp hay là một tuple fona fide được yêu cầu. "Dấu ngoặc" là sai lệch vì bạn có thể tạo một bộ dữ liệu mà không có dấu ngoặc đơn ở nơi khác và sau đó sử dụng nó trong exceptdòng. Nó chỉ nhất thiết phải được ngoặc đơn nếu được tạo trong exceptdòng.
BallpointBen

5
@JosephBani, còn biểu thức máy phát điện thì sao?
jammertheprogrammer

12
@JosephBani Điều đó không đúng chút nào. Trong 2 + (x * 2), (x * 2)chắc chắn không phải là một tuple. Dấu ngoặc là một cấu trúc nhóm chung. Đặc điểm xác định của một tuple là nó chứa dấu phẩy - xem tài liệu Python : "Lưu ý rằng đó thực sự là dấu phẩy tạo ra một tuple, không phải dấu ngoặc đơn."
Soren Bjornstad

314

Làm cách nào để tôi bắt được nhiều ngoại lệ trong một dòng (ngoại trừ khối)

Làm cái này:

try:
    may_raise_specific_errors():
except (SpecificErrorOne, SpecificErrorTwo) as error:
    handle(error) # might log or have some other default behavior...

Các dấu ngoặc đơn được yêu cầu do cú pháp cũ hơn đã sử dụng dấu phẩy để gán đối tượng lỗi cho tên. Các astừ khóa được sử dụng cho bài tập. Bạn có thể sử dụng bất kỳ tên nào cho đối tượng lỗi, tôi thích errorcá nhân hơn.

Thực hành tốt nhất

Để thực hiện điều này theo cách tương thích hiện tại và chuyển tiếp với Python, bạn cần tách Ngoại lệ bằng dấu phẩy và bọc chúng bằng dấu ngoặc đơn để phân biệt với cú pháp trước đó đã gán đối tượng ngoại lệ cho một tên biến bằng cách theo loại Ngoại lệ được bắt với dấu phẩy

Đây là một ví dụ về cách sử dụng đơn giản:

import sys

try:
    mainstuff()
except (KeyboardInterrupt, EOFError): # the parens are necessary
    sys.exit(0)

Tôi chỉ xác định những ngoại lệ này để tránh ẩn lỗi, nếu tôi gặp phải tôi mong đợi dấu vết ngăn xếp đầy đủ từ đó.

Điều này được ghi lại ở đây: https://docs.python.org/tutorial/errors.html

Bạn có thể gán ngoại lệ cho một biến, ( elà phổ biến, nhưng bạn có thể thích biến dài hơn nếu bạn xử lý ngoại lệ dài hoặc IDE của bạn chỉ làm nổi bật các lựa chọn lớn hơn, như của tôi.) Ví dụ có thuộc tính args. Đây là một ví dụ:

import sys

try:
    mainstuff()
except (KeyboardInterrupt, EOFError) as err: 
    print(err)
    print(err.args)
    sys.exit(0)

Lưu ý rằng trong Python 3, errđối tượng rơi ra khỏi phạm vi khi exceptkhối được kết thúc.

Không dùng nữa

Bạn có thể thấy mã gán lỗi bằng dấu phẩy. Cách sử dụng này, biểu mẫu duy nhất có sẵn trong Python 2.5 trở về trước, không được chấp nhận và nếu bạn muốn mã của mình tương thích về phía trước trong Python 3, bạn nên cập nhật cú pháp để sử dụng biểu mẫu mới:

import sys

try:
    mainstuff()
except (KeyboardInterrupt, EOFError), err: # don't do this in Python 2.6+
    print err
    print err.args
    sys.exit(0)

Nếu bạn thấy việc gán tên dấu phẩy trong cơ sở mã của bạn và bạn đang sử dụng Python 2.5 trở lên, hãy chuyển sang cách làm mới để mã của bạn vẫn tương thích khi bạn nâng cấp.

Người suppressquản lý bối cảnh

Câu trả lời được chấp nhận thực sự là 4 dòng mã, tối thiểu:

try:
    do_something()
except (IDontLikeYouException, YouAreBeingMeanException) as e:
    pass

Các try, except, passđường có thể bị xử lý theo một đường duy nhất với các nhà quản lý bối cảnh đàn áp, có sẵn trong Python 3.4 :

from contextlib import suppress

with suppress(IDontLikeYouException, YouAreBeingMeanException):
     do_something()

Vì vậy, khi bạn muốn passtrên một số ngoại lệ nhất định, sử dụng suppress.


2
Tốt bổ sung suppress, rất nhiều dễ đọc hơn so chỉ làm passtrênexcept
Mache

50

Từ tài liệu Python -> 8.3 Xử lý ngoại lệ :

Một trycâu lệnh có thể có nhiều hơn một mệnh đề ngoại trừ, để chỉ định các trình xử lý cho các ngoại lệ khác nhau. Nhiều nhất một xử lý sẽ được thực hiện. Trình xử lý chỉ xử lý các trường hợp ngoại lệ xảy ra trong mệnh đề thử tương ứng, không xử lý trong các trình xử lý khác của cùng một câu lệnh thử. Một mệnh đề ngoại lệ có thể đặt tên cho nhiều trường hợp ngoại lệ là một tuple được ngoặc đơn, ví dụ:

except (RuntimeError, TypeError, NameError):
    pass

Lưu ý rằng các dấu ngoặc đơn xung quanh bộ dữ liệu này là bắt buộc, vì ngoại trừ ValueError, e:cú pháp được sử dụng cho những gì thường được viết như except ValueError as e:trong Python hiện đại (được mô tả bên dưới). Cú pháp cũ vẫn được hỗ trợ để tương thích ngược. Điều này có nghĩa except RuntimeError, TypeErrorlà không tương đương except (RuntimeError, TypeError):nhưng except RuntimeError as TypeError:không phải là những gì bạn muốn.


35

Nếu bạn thường xuyên sử dụng một số lượng lớn các trường hợp ngoại lệ, bạn có thể xác định trước một bộ dữ liệu, vì vậy bạn không phải nhập lại chúng nhiều lần.

#This example code is a technique I use in a library that connects with websites to gather data

ConnectErrs  = (URLError, SSLError, SocketTimeoutError, BadStatusLine, ConnectionResetError)

def connect(url, data):
    #do connection and return some data
    return(received_data)

def some_function(var_a, var_b, ...):
    try: o = connect(url, data)
    except ConnectErrs as e:
        #do the recovery stuff
    blah #do normal stuff you would do if no exception occurred

GHI CHÚ:

  1. Nếu bạn, cũng, cần phải bắt các ngoại lệ khác ngoài các trường hợp trong bộ dữ liệu được xác định trước, bạn sẽ cần xác định một ngoại trừ khác.

  2. Nếu bạn không thể chấp nhận một biến toàn cục, hãy xác định nó trong hàm main () và chuyển nó xung quanh nơi cần thiết ...


17

Một trong những cách để làm điều này là ..

try:
   You do your operations here;
   ......................
except(Exception1[, Exception2[,...ExceptionN]]]):
   If there is any exception from the given exception list, 
   then execute this block.
   ......................
else:
   If there is no exception then execute this block. 

và một cách khác là tạo phương thức thực hiện tác vụ được thực hiện bởi exceptkhối và gọi nó thông qua tất cả các exceptkhối mà bạn viết ..

try:
   You do your operations here;
   ......................
except Exception1:
    functionname(parameterList)
except Exception2:
    functionname(parameterList)
except Exception3:
    functionname(parameterList)
else:
   If there is no exception then execute this block. 

def functionname( parameters ):
   //your task..
   return [expression]

Tôi biết rằng cách thứ hai không phải là cách tốt nhất để làm điều này, nhưng tôi chỉ chỉ ra một số cách để làm điều này.


Tôi đang sử dụng cái thứ hai vì tôi có hai ngoại lệ khác nhau, mỗi trường hợp cần được xử lý khác nhau. Có điều gì sai khi làm theo cách đó?
Majikman

@majikman Phương pháp thứ hai với nhiều mệnh đề, mỗi mệnh đề gọi cùng một chức năng không phải là tốt nhất khi bạn đang cố gắng không lặp lại chính mình và làm điều tương tự cho hai trường hợp ngoại lệ. (Xem các câu trả lời khác cho đúng cách để làm điều đó). Tuy nhiên, có nhiều exceptmệnh đề là bình thường khi bạn muốn xử lý các ngoại lệ khác nhau.
Eponymous
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.