2012-01-06 42 views
48

Tôi đang cố gắng để bắt một ngoại lệ trong một thread và tái nâng nó trong các chủ đề chính:Re-nâng Python ngoại lệ và giữ gìn vết đống

import threading 
import sys 

class FailingThread(threading.Thread): 
    def run(self): 
     try: 
      raise ValueError('x') 
     except ValueError: 
      self.exc_info = sys.exc_info() 

failingThread = FailingThread() 
failingThread.start() 
failingThread.join() 

print failingThread.exc_info 
raise failingThread.exc_info[1] 

này về cơ bản hoạt động và mang lại kết quả như sau:

(<type 'exceptions.ValueError'>, ValueError('x',), <traceback object at 0x1004cc320>) 
Traceback (most recent call last): 
    File "test.py", line 16, in <module> 
    raise failingThread.exc_info[1] 

Tuy nhiên, nguồn ngoại lệ trỏ tới dòng 16, nơi xảy ra sự cố lại. Trường hợp ngoại lệ ban đầu xuất phát từ dòng 7. Làm thế nào để tôi phải thay đổi chính chủ đề để các đầu ra đọc:

Traceback (most recent call last): 
    File "test.py", line 7, in <module> 
+0

tuyệt vời, tôi đã được tái huy động ngoại lệ từ chủ đề khác nữa, nhưng không bao giờ đi xa bạn muốn :) –

+0

trùng lặp có thể xảy ra ["Ngoại lệ bên trong" (với traceback) bằng Python?] (Http://stackoverflow.com/questions/1350671/inner-exception-with-traceback-in-python) –

Trả lời

50

Bạn cần phải sử dụng tất cả ba lập luận nhằm nâng cao:

raise failingThread.exc_info[0], failingThread.exc_info[1], failingThread.exc_info[2] 

đi qua các đối tượng traceback trong như là đối số thứ ba bảo stack.

Từ help('raise'):

Nếu một đối tượng thứ ba là hiện tại và không None, nó phải là một đối tượng traceback (xem phần Loại tiêu chuẩn phân cấp), và nó là thay thay vì hiện tại vị trí là nơi xảy ra trường hợp ngoại lệ . Nếu đối tượng thứ ba có mặt và không phải là đối tượng truy nguyên hoặc None, ngoại lệ TypeError được nêu ra. Biểu mẫu ba biểu thức ba biểu thức raise hữu ích khi tăng lại ngoại lệ một cách minh bạch trong một khoản ngoại trừ, nhưng raise không có biểu thức nên được ưu tiên nếu ngoại lệ được nâng lên là ngoại lệ hoạt động gần đây nhất hiện tại phạm vi.

Trong trường hợp cụ thể này, bạn không thể sử dụng phiên bản không có biểu thức.

+3

Lưu ý: điều này không hoạt động trong python 3. –

+4

@AndyHayden Thật vậy, trong Python 3 [nâng cao] (http://docs.python.org/3/reference/simple_stmts.html#the-raise-statement) sẽ phải được gọi bằng cách nào đó như 'raise failingThread.exc_info [0 ] (failingThread.exc_info [1]). with_traceback (failin gThread.exc_info [2]) '. Mặc dù trong Python 3, 'raise AnotherError từ storage_exception' có thể cung cấp một hiệu chỉnh tốt hơn nữa là hiệu chỉnh –

+0

, cái đầu tiên sẽ là' raise failingThread.exc_info [1] .with_traceback (failingThread.exc_info [2]) 'theo [bình luận này] (http://stackoverflow.com/questions/18188563/how-to-re-raise-an-exception-in-nested-try-except-blocks/18188660?noredirect=1#comment26654548_18188660) –

0

bạn có thể viết nó hơi như thế này:

try: 
    raise ValueError('x') 
except ValueError as ex: 
    self.exc_info = ex 

và sau đó sử dụng stacktrace từ ngoại lệ?

1

đoạn mã này hoạt động trong cả hai python 2 & 3:

 1 try: 
----> 2  raise KeyError('Default key error message') 
     3 except KeyError as e: 
     4  e.args = ('Custom message when get re-raised',) #The comma is not a typo, it's there to indicate that we're replacing the tuple that e.args pointing to with another tuple that contain the custom message. 
     5  raise 
+0

Tại sao lại là downvote? – pkoch

+1

Tôi có thể đoán tại sao downvote. Giải pháp này chỉ hợp lệ nếu không có bất kỳ xử lý ngoại lệ nào. Hãy tưởng tượng rằng khi bắt ngoại lệ, bạn cố gắng cập nhật trạng thái trong db và điều đó cũng không thành công. Trong trường hợp đó, ngoại lệ sẽ được nâng lên là trường hợp ngoại lệ cuối cùng (giao dịch db không thành công) và không phải là giao dịch đầu tiên chúng tôi bắt được. – odedfos

Các vấn đề liên quan