Làm thế nào để bỏ qua các ngoại lệ


777

Khi bạn chỉ muốn thực hiện thử - ngoại trừ không xử lý ngoại lệ, làm thế nào để bạn làm điều đó trong Python?

Là cách sau đây đúng để làm điều đó?

try:
    shutil.rmtree(path)
except:
    pass

10
Thật kỳ lạ là không ai đề cập đến nó cho đến bây giờ (tôi đã làm trong câu trả lời của tôi), nhưng đối với chức năng cụ thể này, bạn chỉ có thể làm shutil.rmtree(path, ignore_errors=True). Điều này sẽ không áp dụng cho hầu hết các chức năng, tuy nhiên.
Aaron Hall

9
Đọc quan trọng khi suy nghĩ về việc bỏ qua các ngoại lệ: Tại sao lại là ngoại trừ: vượt qua một thực hành lập trình tồi?
chọc

3
Hãy tưởng tượng làm điều này trong cuộc sống thực. thử: get_cash ('$ 1000') ngoại trừ: vượt qua # meh, nó có thể sẽ ổn
Grokodile

Cuộc sống thực:try: rob() except: run()
PatrickT

Câu trả lời:


1039
try:
    doSomething()
except: 
    pass

hoặc là

try:
    doSomething()
except Exception: 
    pass

Sự khác biệt là cái đầu tiên cũng sẽ bắt KeyboardInterrupt, SystemExitvà những thứ như thế, có nguồn gốc trực tiếp từ exceptions.BaseException, không exceptions.Exception.

Xem tài liệu để biết chi tiết:


4
Lưu ý rằng cả StopIteration và Cảnh báo đều thừa hưởng từ Ngoại lệ. Tùy thuộc vào nhu cầu của bạn, bạn có thể muốn kế thừa từ StandardError thay thế.
Ben Trống

1
Điều này là đúng, nhưng nếu bạn không cẩn thận, bạn có thể gặp phải các lỗi tinh vi (đặc biệt là nếu bạn đang làm gì đó ngoài việc truyền StopIteration).
Jason Baker

17
-1, try: shuti.rmtree(...) except: passsẽ triệt để khắc phục mọi lỗi (ngay cả khi bạn viết sai chính tả shutildẫn đến a NameError) - ít nhất là làmexcept OSError:
dbr

44
Câu trả lời này, trong khi có nhiều thông tin, đang thiếu một thông tin quan trọng - bạn không bao giờ nên bắt ngoại lệ theo cách này. Thay vào đó, bạn nên luôn cố gắng chỉ nắm bắt những ngoại lệ mà bạn quan tâm, nếu không bạn sẽ gặp ác mộng khi săn lùng những con bọ tầm thường, bị ẩn bởi "ngoại trừ" chung chung của bạn. Xem câu trả lời của dbr để biết thêm. (Tôi biết đây không phải là câu hỏi ban đầu - nhưng bất kỳ ai đang tìm kiếm câu hỏi này sẽ chỉ lấy đoạn trích của bạn và sử dụng nó như hiện tại)
johndodo

139

Nói chung, nó được coi là cách thực hành tốt nhất để chỉ bắt những lỗi bạn quan tâm. Trong trường hợp shutil.rmtreeđó có thể là OSError:

>>> shutil.rmtree("/fake/dir")
Traceback (most recent call last):
    [...]
OSError: [Errno 2] No such file or directory: '/fake/dir'

Nếu bạn muốn âm thầm bỏ qua lỗi đó, bạn sẽ làm:

try:
    shutil.rmtree(path)
except OSError:
    pass

Tại sao? Giả sử bạn (bằng cách nào đó) vô tình truyền vào hàm một số nguyên thay vì một chuỗi, như:

shutil.rmtree(2)

Nó sẽ đưa ra lỗi "TypeError: buộc vào Unicode: cần chuỗi hoặc bộ đệm, int find" - bạn có thể không muốn bỏ qua điều đó, điều này có thể khó gỡ lỗi.

Nếu bạn chắc chắn muốn bỏ qua tất cả các lỗi, hãy nắm bắt Exceptionhơn là một except:tuyên bố trần trụi . Một lần nữa, tại sao?

Không chỉ định một ngoại lệ bắt mọi ngoại lệ, bao gồm SystemExitngoại lệ mà ví dụ sys.exit()sử dụng:

>>> try:
...     sys.exit(1)
... except:
...     pass
... 
>>>

So sánh điều này với những điều sau đây, lối thoát chính xác:

>>> try:
...     sys.exit(1)
... except Exception:
...     pass
... 
shell:~$ 

Nếu bạn muốn viết mã hành xử tốt hơn bao giờ hết, OSErrorngoại lệ có thể biểu thị các lỗi khác nhau, nhưng trong ví dụ trên chúng tôi chỉ muốn bỏ qua Errno 2, vì vậy chúng tôi thậm chí có thể cụ thể hơn:

import errno

try:
    shutil.rmtree(path)
except OSError as e:
    if e.errno != errno.ENOENT:
        # ignore "No such file or directory", but re-raise other errors
        raise

1
shutil.rmtreekhông phải là ví dụ tốt nhất, bởi vì bạn sẽ chỉ sử dụng ignore_errors=Truecho chức năng đó ..
wim

113

Khi bạn chỉ muốn thực hiện một thử bắt mà không xử lý ngoại lệ, làm thế nào để bạn làm điều đó trong Python?

Nó phụ thuộc vào những gì bạn có nghĩa là "xử lý."

Nếu bạn muốn bắt nó mà không thực hiện bất kỳ hành động nào, mã bạn đã đăng sẽ hoạt động.

Nếu bạn muốn nói rằng bạn muốn thực hiện hành động đối với một ngoại lệ mà không ngăn chặn ngoại lệ đi lên ngăn xếp, thì bạn muốn một cái gì đó như thế này:

try:
    do_something()
except:
    handle_exception()
    raise  #re-raise the exact same exception that was thrown

88

Đầu tiên tôi trích dẫn câu trả lời của Jack o'Connor từ chủ đề này . Các chủ đề được tham chiếu đã đóng cửa vì vậy tôi viết ở đây:

"Có một cách mới để thực hiện điều này trong Python 3.4:

from contextlib import suppress

with suppress(Exception):
    # your code

Đây là cam kết đã thêm nó: http://hg.python.org/cpython/rev/406b47c64480

Và đây là tác giả, Raymond Hettinger, nói về điều này và tất cả các loại độ nóng khác của Python: https://youtu.be/OSGv2VnC0go?t=43m23s

Bổ sung của tôi vào đây là tương đương Python 2.7:

from contextlib import contextmanager

@contextmanager
def ignored(*exceptions):
    try:
        yield
    except exceptions:
        pass

Sau đó, bạn sử dụng nó như trong Python 3.4:

with ignored(Exception):
    # your code

55

Để hoàn thiện:

>>> def divide(x, y):
...     try:
...         result = x / y
...     except ZeroDivisionError:
...         print("division by zero!")
...     else:
...         print("result is", result)
...     finally:
...         print("executing finally clause")

Cũng lưu ý rằng bạn có thể nắm bắt ngoại lệ như thế này:

>>> try:
...     this_fails()
... except ZeroDivisionError as err:
...     print("Handling run-time error:", err)

... và nêu lại ngoại lệ như thế này:

>>> try:
...     raise NameError('HiThere')
... except NameError:
...     print('An exception flew by!')
...     raise

... ví dụ từ hướng dẫn python .


43

Làm thế nào để bỏ qua các trường hợp ngoại lệ?

Có một số cách để làm điều này.

Tuy nhiên, sự lựa chọn của ví dụ có một giải pháp đơn giản không bao gồm trường hợp chung.

Cụ thể với ví dụ:

Thay vì

try:
    shutil.rmtree(path)
except:
    pass

Làm cái này:

shutil.rmtree(path, ignore_errors=True)

Đây là một đối số cụ thể để shutil.rmtree. Bạn có thể thấy sự trợ giúp về nó bằng cách thực hiện như sau và bạn cũng sẽ thấy nó cũng có thể cho phép các chức năng về lỗi.

>>> import shutil
>>> help(shutil.rmtree)

Vì điều này chỉ bao gồm trường hợp hẹp của ví dụ, tôi sẽ trình bày thêm cách xử lý vấn đề này nếu những đối số từ khóa đó không tồn tại.

Cách tiếp cận chung

Vì ở trên chỉ bao gồm trường hợp hẹp của ví dụ, tôi sẽ trình bày thêm cách xử lý vấn đề này nếu những đối số từ khóa đó không tồn tại.

Mới trong Python 3,4:

Bạn có thể nhập trình suppressquản lý bối cảnh:

from contextlib import suppress

Nhưng chỉ loại bỏ ngoại lệ cụ thể nhất:

with suppress(FileNotFoundError):
    shutil.rmtree(path)

Bạn sẽ âm thầm bỏ qua một FileNotFoundError:

>>> with suppress(FileNotFoundError):
...     shutil.rmtree('bajkjbkdlsjfljsf')
... 
>>> 

Từ các tài liệu :

Như với bất kỳ cơ chế nào khác loại bỏ hoàn toàn các ngoại lệ, trình quản lý bối cảnh này chỉ nên được sử dụng để khắc phục các lỗi rất cụ thể trong đó việc âm thầm tiếp tục thực hiện chương trình được biết là điều nên làm.

Lưu ý rằng suppressFileNotFoundErrorchỉ có sẵn trong Python 3.

Nếu bạn muốn mã của mình cũng hoạt động trong Python 2, hãy xem phần tiếp theo:

Python 2 & 3:

Khi bạn chỉ muốn thử / ngoại trừ mà không xử lý ngoại lệ, làm thế nào để bạn làm điều đó trong Python?

Là cách sau đây đúng để làm điều đó?

try :
    shutil.rmtree ( path )
except :
    pass

Đối với mã tương thích Python 2, passlà cách chính xác để có một câu lệnh không có op. Nhưng khi bạn làm một trần except:, đó là giống như làm except BaseException:trong đó bao gồm GeneratorExit, KeyboardInterruptSystemExit, và nói chung, bạn không muốn bắt những điều đó.

Trong thực tế, bạn nên cụ thể trong việc đặt tên ngoại lệ như bạn có thể.

Đây là một phần của hệ thống phân cấp ngoại lệ Python (2) và như bạn có thể thấy, nếu bạn nắm bắt được các Ngoại lệ chung hơn, bạn có thể ẩn các vấn đề bạn không mong đợi:

BaseException
 +-- SystemExit
 +-- KeyboardInterrupt
 +-- GeneratorExit
 +-- Exception
      +-- StopIteration
      +-- StandardError
      |    +-- BufferError
      |    +-- ArithmeticError
      |    |    +-- FloatingPointError
      |    |    +-- OverflowError
      |    |    +-- ZeroDivisionError
      |    +-- AssertionError
      |    +-- AttributeError
      |    +-- EnvironmentError
      |    |    +-- IOError
      |    |    +-- OSError
      |    |         +-- WindowsError (Windows)
      |    |         +-- VMSError (VMS)
      |    +-- EOFError
... and so on

Bạn có thể muốn bắt OSError ở đây và có lẽ ngoại lệ bạn không quan tâm là nếu không có thư mục.

Chúng tôi có thể nhận được số lỗi cụ thể đó từ errnothư viện và phát lại nếu chúng tôi không có:

import errno

try:
    shutil.rmtree(path)
except OSError as error:
    if error.errno == errno.ENOENT: # no such file or directory
        pass
    else: # we had an OSError we didn't expect, so reraise it
        raise 

Lưu ý, tăng trần làm tăng ngoại lệ ban đầu, đó có thể là những gì bạn muốn trong trường hợp này. Được viết chính xác hơn, vì chúng ta không thực sự cần phải rõ ràng passvới mã trong xử lý ngoại lệ:

try:
    shutil.rmtree(path)
except OSError as error:
    if error.errno != errno.ENOENT: # no such file or directory
        raise 

11

Khi bạn chỉ muốn thực hiện một thử bắt mà không xử lý ngoại lệ, làm thế nào để bạn làm điều đó trong Python?

Điều này sẽ giúp bạn in ngoại lệ là gì :( tức là thử bắt mà không xử lý ngoại lệ và in ngoại lệ.)

import sys
try:
    doSomething()
except:
    print "Unexpected error:", sys.exc_info()[0]

10
try:
      doSomething()
except Exception: 
    pass
else:
      stuffDoneIf()
      TryClauseSucceeds()

FYI mệnh đề khác có thể đi sau tất cả các ngoại lệ và sẽ chỉ được chạy nếu mã trong lần thử không gây ra ngoại lệ.


1
Cuối cùng là một lời giải thích tốt elsetrong bối cảnh này. Và để thêm rằng finallysẽ luôn luôn chạy sau bất kỳ (hoặc không có ngoại lệ).
not2qubit

5

Tôi cần thiết để bỏ qua sai sót trong nhiều lệnh và fuckit đã làm các trick

import fuckit

@fuckit
def helper():
    print('before')
    1/0
    print('after1')
    1/0
    print('after2')

helper()

+1 vì Bạn chắc chắn đã tạo ra ngày của tôi vì bên trong mã nguồn này, bạn có thể tìm hiểu một số điều cực kỳ hữu ích như sửa đổi ngăn xếp trực tiếp
WBAR

3

Trong Python, chúng tôi xử lý các ngoại lệ tương tự như ngôn ngữ khác, nhưng sự khác biệt là một số khác biệt về cú pháp, ví dụ:

try:
    #Your code in which exception can occur
except <here we can put in a particular exception name>:
    # We can call that exception here also, like ZeroDivisionError()
    # now your code
# We can put in a finally block also
finally:
    # Your code...

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.