2008-10-03 26 views
6

Tôi đang viết một ứng dụng gỡ lỗi nhỏ cho một số bộ chúng tôi đang phát triển và tôi muốn giới thiệu cho một số người dùng để xem liệu họ có thể kích động mọi sự cố không. Có ai biết một cách hiệu quả gói một ứng dụng wxPython để bắt bất kỳ và tất cả các trường hợp ngoại lệ unhandled mà có thể gây ra các ứng dụng sụp đổ?Làm thế nào tôi có thể nắm bắt tất cả các ngoại lệ từ một ứng dụng wxPython?

Lý tưởng nhất là tôi muốn chụp tất cả đầu ra (không chỉ là lỗi) và ghi nó vào một tệp. Bất kỳ ngoại lệ không được xử lý nào phải đăng nhập vào tệp hiện tại và sau đó cho phép ngoại lệ chuyển sang như thường lệ (tức là quá trình ghi nhật ký phải trong suốt).

Tôi chắc chắn một người nào đó phải làm điều gì đó dọc theo các dòng này trước đây, nhưng tôi đã không quản lý để bật lên bất kỳ thứ gì có vẻ hữu ích qua google.

Trả lời

6

Đối đăng nhập đầu ra tiêu chuẩn, bạn có thể sử dụng một wrapper stdout, như thế này một:

from __future__ import with_statement 

class OutWrapper(object): 
    def __init__(self, realOutput, logFileName): 
     self._realOutput = realOutput 
     self._logFileName = logFileName 

    def _log(self, text): 
     with open(self._logFileName, 'a') as logFile: 
      logFile.write(text) 

    def write(self, text): 
     self._log(text) 
     self._realOutput.write(text) 

Sau đó bạn phải khởi tạo nó trong tập tin Python chính của bạn (một trong đó chạy tất cả mọi thứ):

import sys  
sys.stdout = OutWrapper(sys.stdout, r'c:\temp\log.txt') 

Khi đăng nhập ngoại lệ, điều dễ nhất cần thực hiện là quấn MainLoop phương thức wx.App trong một lần thử..except, sau đó trích xuất thông tin ngoại lệ, lưu nó theo một cách nào đó và sau đó tăng lại ngoại lệ thông qua raise, ví dụ:

try: 
    app.MainLoop() 
except: 
    exc_info = sys.exc_info() 
    saveExcInfo(exc_info) # this method you have to write yourself 
    raise 
+0

Chúc mừng Dzinx - Tôi đã kết thúc bằng cách sử dụng kết hợp đề xuất của bạn và monopocalypse's –

+3

Tôi đã thử làm điều này trong ứng dụng của mình để bắt ngoại lệ và hiển thị hộp thoại lỗi thân thiện, nhưng nó không hoạt động. Có vẻ như vì wxPython sinh ra một luồng khác cho App.MainLoop() mà các ngoại lệ nằm ngoài phạm vi của khối try/except tại điểm đó. – Soviut

1

Có nhiều cách khác nhau. Bạn có thể đặt một khối try..catch trong wxApplication :: OnInit, tuy nhiên, điều đó sẽ không phải lúc nào cũng làm việc với Gtk.

Một lựa chọn tốt đẹp sẽ được ghi đè lên các ứng dụng :: handleEvent trong wxApplication có nguồn gốc lớp học của bạn, và viết code như thế này:

void Application::HandleEvent(wxEvtHandler* handler, wxEventFunction func, wxEvent& event) const 
{ 
    try 
    { 
     wxAppConsole::HandleEvent(handler, func, event); 
    } 
    catch (const std::exception& e) 
    { 
     wxMessageBox(std2wx(e.what()), _("Unhandled Error"), 
      wxOK | wxICON_ERROR, wxGetTopLevelParent(wxGetActiveWindow())); 
    } 
} 

Đó là một C++ ví dụ, nhưng bạn chắc chắn có thể dịch để Python dễ dàng.

9

Đối với việc xử lý ngoại lệ, giả sử tập tin đăng nhập của bạn được mở ra như log:

import sys 
import traceback 

def excepthook(type, value, tb): 
    message = 'Uncaught exception:\n' 
    message += ''.join(traceback.format_exception(type, value, tb)) 
    log.write(message) 

sys.excepthook = excepthook 
+0

Chúc mừng monopocalypse - Tôi đã kết thúc bằng cách sử dụng kết hợp đề xuất của bạn và Dzinx's. Tôi chỉ ước tôi có thể chấp nhận cả hai câu trả lời của bạn! –

3

Bạn có thể sử dụng

sys.excepthook

(thấy Python docs)

và gán một số đối tượng tùy chỉnh cho nó, mà sẽ bắt tất cả các ngoại lệ không bị bắt trước đó trong mã của bạn. Sau đó bạn có thể đăng nhập bất kỳ tin nhắn nào vào bất kỳ tập tin nào bạn muốn, cùng với traceback và làm bất cứ điều gì bạn muốn với ngoại lệ (reraise nó, hiển thị thông báo lỗi và cho phép người dùng tiếp tục sử dụng ứng dụng của bạn, vv).

Để đăng xuất stdout - cách tốt nhất cho tôi là viết một cái gì đó tương tự như OutWrapper của DzinX.

Nếu bạn đang ở giai đoạn gỡ lỗi, hãy xem xét xóa các tệp nhật ký của bạn sau mỗi lần nhập. Điều này làm hại hiệu suất rất nhiều, nhưng nếu bạn quản lý để gây ra segfault trong một số mã C cơ bản, các bản ghi của bạn sẽ không đánh lừa bạn.

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