2009-12-06 37 views
12

Có một số câu hỏi tương tự, nhưng không có câu trả lời nào tôi yêu cầu.Tăng ngoại lệ chưa được xử lý trong chuỗi trong chuỗi chính?

Nếu tôi tạo chủ đề qua threading.Thread, sau đó ném ngoại lệ bị hủy, các chủ đề đó sẽ bị chấm dứt. Tôi muốn giữ lại bản in mặc định trong các chi tiết ngoại lệ với dấu vết ngăn xếp, nhưng cũng làm giảm toàn bộ quá trình.

Tôi đã xem xét rằng có thể bắt tất cả ngoại lệ trong chuỗi và reraise chúng trên đối tượng chuỗi chính hoặc có thể tự thực hiện xử lý ngoại lệ mặc định và sau đó tăng SystemExit trên chính chủ đề.

Cách tốt nhất để giải quyết vấn đề này là gì?

Trả lời

15

Tôi đã viết về Re-throwing exceptions in Python, bao gồm một cái gì đó rất giống như đây là một ví dụ.

On sợi nhân của bạn, bạn thực hiện điều này (Python 2.x, xem dưới đây để biết phiên bản 3.x Python):

try: 
    self.result = self.do_something_dangerous() 
except Exception, e: 
    import sys 
    self.exc_info = sys.exc_info() 

và trên chủ đề chính của bạn, bạn làm như sau:

if self.exc_info: 
    raise self.exc_info[1], None, self.exc_info[2] 
return self.result 

Ngoại lệ sẽ xuất hiện trong chuỗi chính giống như nó đã được nâng lên trong chuỗi công nhân.

Python 3.x:

try: 
    self.result = self.do_something_dangerous() 
except Exception as e: 
    import sys 
    self.exc_info = sys.exc_info() 

và trên thread chính của bạn:

if self.exc_info: 
    raise self.exc_info[1].with_traceback(self.exc_info[2]) 
return self.result 
+0

không phải là bạn muốn ném 'thrdobj.exc_info' vào chuỗi chính và tại sao lại loại bỏ loại ngoại lệ khi bạn quay lại? –

+0

tôi thấy bây giờ, đã phải đọc lên trên tuyên bố nâng cao 3arg. nhưng câu hỏi về 'self' vẫn đứng vững, cảm ơn vì câu trả lời hay, tôi sẽ thử nó –

+0

Tôi không chắc câu hỏi của bạn về bản thân là gì. Mã này xuất phát từ một đối tượng được sử dụng để trì hoãn công việc lên một chuỗi công nhân, vì vậy cùng một đối tượng chạy mã trong luồng công nhân và chủ đề chính. –

9

Ngoại lệ duy nhất một sợi thứ cấp đáng tin cậy có thể tăng trong các chủ đề chính là KeyboardInterrupt: cách thread thứ cấp hiện nó là bằng cách gọi hàm thread.interrupt_main(). Không có cách nào để liên kết thông tin bổ sung (về lý do ngoại lệ) với đối tượng ngoại lệ được tăng lên - sau này luôn là chỉ đơn giản là KeyboardInterrupt. Vì vậy, bạn cần phải cất giấu thông tin đó ở một nơi khác, ví dụ: trên một phiên bản chuyên dụng của Queue.Queue - thông tin đó có thể bao gồm kết quả mà chuỗi thứ cấp có thể nhận được qua sys.exc_info() và mọi thứ khác mà bạn thấy hữu ích trong khóa học. Chủ đề chính sẽ cần khôi phục thông tin bổ sung đó (và xem xét rằng hàng đợi sẽ trống nếu bàn phím ngắt thực sự là do người dùng nhấn control-C hoặc tương tự, vì vậy, hãy sử dụng get_nowait và sẵn sàng để đối phó với một ngoại lệ Queue.Empty, ví dụ), định dạng nó tuy nhiên bạn mong muốn, và chấm dứt (nếu tất cả các chủ đề phụ là daemon s, toàn bộ quá trình chấm dứt khi chủ đề chính chấm dứt).

+0

liên kết tài liệu luồng được cập nhật: https://docs.python.org/3.6/library/_thread.html?highlight=interrupt_main#_thread.interrupt_main – user2682863