2011-01-22 23 views
14

Nếu tôi chạy đoạn mã sau từ một thiết bị đầu cuối, tôi nhận được một thông báo lỗi hữu ích trong các thiết bị đầu cuối:Tôi có thể làm cho các ngoại lệ im lặng to hơn trong tkinter như thế nào?

import Tkinter as tk 

master = tk.Tk() 

def callback(): 
    raise UserWarning("Exception!") 

b = tk.Button(master, text="This will raise an exception", command=callback) 
b.pack() 

tk.mainloop() 

Tuy nhiên, nếu tôi chạy nó mà không có một thiết bị đầu cuối (ví dụ, bằng cách nhấp đúp biểu tượng), các thông báo lỗi bị chặn.

Trong ứng dụng Tkinter thực tế, phức tạp hơn của tôi, tôi thích giao diện đồ họa có khả năng chống va chạm nhỏ. Tôi không thích rằng người dùng của tôi gặp khó khăn trong việc cung cấp cho tôi phản hồi hữu ích để khắc phục hành vi không mong muốn kết quả.

Tôi nên xử lý điều này như thế nào? Có cách nào tiêu chuẩn để vạch trần các vết tracebacks hoặc stderror hoặc không có trong ứng dụng Tkinter không? Tôi đang tìm kiếm một cái gì đó thanh lịch hơn là đặt thử/ngoại trừ ở khắp mọi nơi.

EDIT: Jochen Ritzel đưa ra một câu trả lời tuyệt vời bên dưới bật lên một hộp cảnh báo và đề cập đến việc đính kèm nó vào một lớp học. Chỉ cần làm rõ điều này:

import Tkinter as tk 
import traceback, tkMessageBox 

class App: 
    def __init__(self, master): 
     master.report_callback_exception = self.report_callback_exception 
     self.frame = tk.Frame(master) 
     self.frame.pack() 
     b = tk.Button(
      self.frame, text="This will cause an exception", 
      command=self.cause_exception) 
     b.pack() 

    def cause_exception(self): 
     a = [] 
     a.a = 0 #A traceback makes this easy to catch and fix 

    def report_callback_exception(self, *args): 
     err = traceback.format_exception(*args) 
     tkMessageBox.showerror('Exception', err) 

root = tk.Tk() 
app = App(root) 
root.mainloop() 

Sự nhầm lẫn còn lại của tôi: Jochen đề cập đến khả năng có các chức năng báo cáo ngoại lệ khác nhau trong các khung khác nhau. Tôi chưa thấy làm thế nào để làm điều đó. Điều này có hiển nhiên không?

+0

Ngoại lệ vẫn là đầu ra khi bạn nhấp đúp vào biểu tượng. Nó chỉ là bạn không in tiêu chuẩn ra bất cứ nơi nào. – Falmarri

+0

Đồng ý! Tôi đang tìm người để giới thiệu một cách thanh lịch/tiêu chuẩn để phơi bày stdout hoặc stderror cho người dùng. – Andrew

+1

Lớp 'Ứng dụng' là một khung, thường xuất phát từ' tk.Frame'. Nếu chương trình của bạn có hai lớp khung khác nhau được sử dụng cho những thứ khác nhau, thì mỗi lớp khung có thể có phiên bản 'report_callback_exception()' riêng của nó hiển thị lỗi theo một cách khác. –

Trả lời

21

report_callback_exception để làm điều này:

import traceback 
import tkMessageBox 

# You would normally put that on the App class 
def show_error(self, *args): 
    err = traceback.format_exception(*args) 
    tkMessageBox.showerror('Exception',err) 
# but this works too 
tk.Tk.report_callback_exception = show_error 

Nếu bạn không nhập 'Tkinter như tk', sau đó làm

Tkinter.Tk.report_callback_exception = show_error 
+0

Tuyệt vời, cảm ơn bạn! Bạn có muốn mở rộng nhận xét của mình về việc đưa nó vào lớp Ứng dụng không? – Andrew

+1

@Andrew: Tôi chỉ có nghĩa là thông thường bạn sẽ viết ứng dụng của mình trong một lớp con ghi đè phương thức này, thay vì thay đổi chính lớp Tk. Chỉ trong trường hợp bạn muốn các chức năng báo cáo khác nhau trong các khung khác nhau. –

+0

Liên quan: [Xử lý ngoại lệ trong python tkinter] (https://stackoverflow.com/a/35073005/3357935) –

1

Lần đầu tiên một followup: Chỉ cần ngày hôm nay, một bản vá trên CPython tracker cho tài liệu tkinter.Tk.report_callback_exception đã làm rõ rằng Jochen's solution được thiết kế. Các bản vá cũng (và chủ yếu) dừng tk từ crashing trên trường hợp ngoại lệ gọi lại khi chạy dưới pythonw trên Windows.

Thứ hai: đây là khởi đầu của một giải pháp để làm cho hàm stderr không có bảng điều khiển (điều này thực sự là một câu hỏi SO riêng biệt).

import sys, tkinter 

root = tkinter.Tk() 

class Stderr(tkinter.Toplevel): 
    def __init__(self): 
     self.txt = tkinter.Text(root) 
     self.txt.pack() 
    def write(self, s): 
     self.txt.insert('insert', s) 

sys.stderr = Stderr() 

1/0 # traceback appears in window 

Cần có thêm cửa sổ bật lên cho đến khi cần và sau đó hiển thị cửa sổ bật lên.

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