Prevent wxPython from showing 'Unhandled exception' dialog - python

I have complex GUI application written in Python and wxPython.
I want it to be certified for Windows Vista, so it has to crash in a way that causes Windows Error Reporting dialog (The one that asks "Do you want to send report to Microsoft?") to appear. This is relevant to test case no 32 from "Certified for Windows Vista Test Cases" document.
Unfortunately when I crash my app with ThreadHijacker tool wxPython shows message like:
Unhandled exception
---------------------------
An unhandled exception occurred. Press "Abort" to terminate the program,
"Retry" to exit the program normally and "Ignore" to try to continue.
---------------------------
Abort Retry Ignore
How can I prevent wxPython from showing this message? I have custom sys.excepthook, but it seems that this dialog is shown before my except hook can interfere.
EDIT:
wxWidgets docs says that wxAppConsole::OnExceptionInMainLoop is called and under MSW it displays some fancy dialog that allows user to choose between the different options. It seems however, that wxPython doesn't allow overloading that function... Does anyone know how to change default behaviour of wxAppConsole::OnExceptionInMainLoop in wxPython?
I prefer solutions that are on Python level over those that go into C/C++
EDIT2:
All in all, I asked at wxPython mailing list, and Robin Dunn answered that he'll look into making wxAppConsole::OnExceptionInMainLoop overridable in next releases of wxPython. Since I couldn't wait, I had to compile my own version of wxPython which does not include that function. It turned out that the presence of wxAppConsole::OnExceptionInMainLoop function can be enabled/disabled by proper setting of compilation flags.

It all ended up with compiling my own wxWidgets and wxPython, with just one compilation flag changed: wxUSE_EXCEPTIONS should be set to 0.
Robin Dunn wrote that he will try to patch wxPython, so this behaviour could be modified without recompiling of the whole library.

If I remember correctly, this is a catch(...) at top level (wxApp) in wxWidgets. You can either use a vectored Exception Handler or _set_se_translator() to get a first shot at the Structured Exception, and exit to WER, i.e. ReportFault() from there.

Is it possible for you to just handle everything? You would have to, I guess, put a try:except: block around every method bound to a widget. You could write a decorator:
def catch_exception(f):
def safe(*args, **kw):
try:
f(*args, **kw)
except Exception, e:
handle_exception(e)
return safe
def handle_exception(e):
# do Vista stuff
sys.exit()
Then decorate any function that could be called by the mainloop (since I presume that's where wxPython does its own catching).

Try http://wiki.python.org/moin/CrashingPython

Related

Checking if the window is working Python3

How can I make a health check of a window by hwnd? Simply put, I need to handle an error if it happens.
The mistake in question:
I assume this can be done with Win32 libraries, but my searches haven't led to anything.
Use SendMessageTimeout() to send the HWND a benign message, like WM_NULL. You can specify whether the function should fail if a timeout elapses, or even fail immediately if the window's thread is hung (not processing messages).

How to remove icon from QMessageBox in PyQt5?

I am trying to code a message box that just pops up and says something and has a single button to close it however as I only have a small amount of text in the box the icon/image to the left of it is huge and looks bad. I want to know how to remove it. I am also having trouble making custom message boxes. Tutorials say that this is how you make a custom message box:
box = QMessageBox()
box.setText('text')
box.addButton(QPushButton('Close', self))
box.exec_()
However this just closes my program and returns a 1. My current code uses the about method of QMessageBox():
box = QMessageBox().about(self, 'About', 'This is a test Program')
However this has that large icon in the text window and I can't seem to do anything else to the box as it just stops the program and returns 1 again
I am in desperate need of some decent PyQt documentation. I can't seem to find documentation on much at all unless it is in C++. For instance I cannot seem to find any information of options other than question and about for QmessageBox. So if someone could also show me where some proper documentation lives it would prevent me asking too many questions here
Rather than PyQt documentation, it is better to directly use Qt documentation. You only need to switch your language mindset from Python to C++, there and back. It is not that difficult. :) See e.g. http://doc.qt.io/qt-4.8/qmessagebox.html#addButton or http://doc.qt.io/qt-4.8/qmessagebox.html#about I think this is very detailed documentation, unrivaled by most other frameworks.
Note that there are three overrides of addButton(). From the documentation it seems that you either need to pass two arguments to box.addButton(QPushButton('Close', self), QMessageBox.RejectRole) (you forgot the role!) or better, you use the override which uses standard buttons, then you only pass one argument: box.addButton(QMessageBox.Close).
And one more tip for you: I also find it easier to debug my program with PySide than PyQt because unlike PyQt, PySide catches the exception, prints that to console and keeps running. While PyQt usually just silently crashes leaving you clueless. Most of the time, I am using shims Qt.py https://pypi.python.org/pypi/Qt.py/0.6.9 or qtpy https://pypi.python.org/pypi/QtPy to be able to switch from PyQt to PySide on the fly. It also allows switching between Qt4 and Qt5 bindings easily.

Consequences of avoiding PyQt Program Crash on Exit by using sip.setdestroyonexit(False)?

I have a PyQt4 program which tend to crash on exit. I have tried forcing exit of QtGui.QMainWindow by using
def closeEvent(self, event):
exit()
But it didn't stop the program from crashing. I also tried to use the
app.setActiveWindow(MainWindow)
exit(app.exec_())
But didn't seems to fix the problem. Finally, I found out a SO post mentioned about the similar probelm which is fixed by setting sip.setdestroyonexit() to False.
Reference
When the Python interpreter exits PyQt4 (by default) calls the C++
destructor of all wrapped instances that it owns. This happens in a
random order and can therefore cause the interpreter to crash. This
behavior can be disabled by calling the sip.setdestroyonexit()
function.
PyQt5 always calls sip.setdestroyonexit() automatically.
I managed to prevent my program from crashing by setting this setting to False.
Now, I am wondering will there be any consequences of setting sip.setdestroyonexit() to False? What will happen if I disable the calls to C++ destructors?

Using wxSpellCheckerDialog in Django is causing a C++ "wxThread::IsMain()" assertion failure

Continued from How to use wxSpellCheckerDialog in Django?
I have added spell checking to Django application using pyenchant.
It works correctly when first run. But when I call it again (or after several runs) it gives following error.
PyAssertionError at /quiz/submit/
C++ assertion "wxThread::IsMain()"
failed at ....\src\msw\evtloop.cpp(244) in wxEventLoop::Dispatch():
only the main thread can process Windows messages
How to fix this?
You don't need wxPython to use pyEnchant. And you certainly shouldn't be using wx stuff with django. wxPython is for desktop GUIs, while django is a web app framework. As "uhz" pointed out, you can't call wxPython methods outside the main thread that wxPython runs in unless you use its threadsafe methods, such as wx.CallAfter. I don't know why you'd call wxPython from Django though.
It seems you are trying to use wx controls from inside Django code, is that correct? If so you are doing a very weird thing :)
When you write a GUI application with wxPython there is one main thread which can process Window messages - the main thread is defined as the one where wx.App was created. You are trying to do a UI thing from a non-UI thread. So probably at first run everything works (everything is performed in the GUI thread) but on second attempt a different python thread (spawned by django?) is performing some illegal GUI actions. You could try using wx.CallAfter which would execute a function from the argument in GUI thread but this is non-blocking. Also I've found something you might consider: wxAnyThread wxAnyThread. But I didn't use it and I don't know if it applies in your case.

Robustly killing Windows programs stuck reporting 'problems'

I am looking for a means to kill a Windows exe program that, when being tested from a python script, crashes and presents a dialog to the user; as this program is invoked many times, and may crash repeatedly, this is not suitable.
The problem dialog is the standard reporting of a Windows error:
"Foo.exe has encountered a problem and needs to close. We are sorry for the inconvenience"
and offers a Debug, Send Error Report, and Don't Send buttons.
I am able to kill other forms of dialog resulting from crashes (e.g. a Debug build's assert failure dialog is OK.)
I have tried taskkill.exe, pskill, and the terminate() function on the Popen object from the subprocess module that was used to invoke the .exe
Has anyone encountered this specific issue, and found a resolution?
I expect automating user input to select the window, and press the "Don't Send" button is one possible solution, but I would like something far simpler if possible
Wouldn't it be easier to disable the error reporting feature?
If you were to use CreateProcessEx or a WinAPI specific function, you might be able to call TerminateProcess or TerminateThread to forcibly end the process.

Categories

Resources