gpt4 book ai didi

Python在wx python应用程序中轻松捕获所有Traceback(最近一次调用最后一次)

转载 作者:行者123 更新时间:2023-12-01 05:00:12 25 4
gpt4 key购买 nike

我使用 wx python 编写了一个 python 应用程序,这是一个相当复杂的脚本、类等。该应用程序从外部源获取 xml 文件并操作它们,这有时会导致脚本的各个不同区域出现意外异常。在 IDLE 中运行应用程序时这很好,我可以在 IDLE shell 中看到任何异常,但我需要将其作为独立的应用程序运行,我使用 py2app 和 pyinstaller。所以切入正题,我的问题是......作为独立应用程序运行时,我想将任何 python 异常打印到 wx.stc.StyledTextCtrl 窗口或类似的窗口,这样我至少可以看到发生的任何奇怪的事情。我研究过使用 tryexcept Exception 捕获异常,但我实际上必须重新编写我的应用程序才能包含这些类型的异常。我有什么选择?这是我的应用程序的一个非常小的示例,显然缺少内容:

import wx
import os
import os.path
import subprocess
import pipes
import platform
import shlex
from subprocess import Popen, PIPE
import sys
import threading
import wx.stc as stc
import traceback

class MainWindow(wx.Frame):
def __init__(self, parent, id, title):
wx.Frame.__init__(self, parent, id, title, size=(600, 550), style=wx.DEFAULT_FRAME_STYLE & ~ (wx.RESIZE_BORDER |
wx.RESIZE_BOX |
wx.MAXIMIZE_BOX))

self.run_params = {}
self.run_params["refresh"] = False
systemType = platform.system()
.........................

app = wx.App()
MainWindow(None, -1, 'My Application')
app.MainLoop()

最佳答案

快速谷歌搜索“wxpython回溯”发现了这篇文章CustomExceptionHandling在 wxpython wiki 上。

维基页面提供的代码示例可以完成比您要求的更多的事情,例如通过电子邮件提交错误报告。我将仅展示如何做适合问题的最简单的事情,但请阅读该页面以获取更多想法。

class MyApp(wx.App):
def OnInit(self):
sys.excepthook = self.OnException
# your existing OnInit code

def OnException(self, type, value, tb):
lines = traceback.format_exception(type, value, tb)
msg = '\n'.join(lines)
# Now create your dialog and display msg

请注意,如果您的应用程序在编写时没有考虑到异常安全,那么未处理的异常很可能意味着您可能处于不可恢复的状态,并且没有简单的方法可以判断您是否处于不可恢复的状态。因此,您的对话框可能应该只有一个“退出”按钮,并且您应该以模态方式显示它,然后在单击后硬退出。

<小时/>

如果您有一个多线程应用程序,这可能不起作用,因为 threading每个线程都有自己的异常处理程序。请参阅#1230540针对此问题的各种解决方案。但有一些注意事项:

  • 您需要主线程调用 sys.excepthook对于你来说,不要直接在工作线程上调用它,或者写你的 excepthook工作线程安全(特别是让它要求主线程代表它创建对话框)。我将在下面展示如何做到这一点,尽管它是未经测试的代码,而且我有一段时间没有使用 wx,所以它可能需要一些工作。
  • 如果您使用Thread子类,而不是按原样使用 target 的类功能,仅Ian Beaver's solution将为你工作;我不会展示这一点,但这并不太棘手。
  • 如果你的 GUI 的主循环没有在主线程上运行(这种情况不常见,但并非不可能或非法),如果没有一些大的改变,这可能无法工作;我不记得如何处理这些。
  • 早期版本的 Python 中存在一些错误,导致其中一些解决方案无法工作;我不知道哪些版本或它们是什么。

所以,这是我未经测试的 wx 定制版本 Jonathan Ellis's solution 的简化版本:

import sys
import threading
import wx

ID_EXCEPTHOOK = wx.NewId()

def EVT_EXCEPTHOOK(win, func):
win.Connect(-1, -1, ID_EXCEPTHOOK, func)

class ExceptionEvent(wx.PyEvent):
def __init__(self, type, value, tb):
super(ExceptionEvent, self).__init__()
self.SetEventType(ID_EXCEPTHOOK)
self.type, self.value, self.tb = type, value, tb

class WorkerThread(threading.Thread):
def __init__(self, main_window, *args, **kwargs):
super(WorkerThread, self).__init__(*args, **kwargs)
self.main_window = main_window
def run(*args, **kwargs):
try:
super(WorkerThread, self).run(*args, **kwargs)
except (KeyboardInterrupt, SystemExit):
raise
except:
wx.PostEvent(self.main_window, ExceptionEvent(*sys.exc_info()))

class MainFrame(wx.Frame):
def __init__(self, parent, id):
# existing code
EVT_EXCEPTHOOK(self, self.OnException)
def OnException(self, event):
sys.excepthook(event.type, event.value, event.tb)

class MyApp(wx.App):
# same as before

现在,无论何时创建线程,都必须使用 WorkerThread而不是Thread ,并将其传递给您的 MainFrame实例作为额外的第一个参数。但想必您创建线程的频率远低于编写可能引发的函数的频率,因此希望这不是问题。(如果这是问题,您可以将代码添加到 WorkerThread 中获取单例应用程序,询问其主窗口并使用它,然后使用 Monkeypatch threading.Thread = WorkerThread 。)

关于Python在wx python应用程序中轻松捕获所有Traceback(最近一次调用最后一次),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26414335/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com