PyQt: нет сообщения об ошибке (трассировка) при выходе

#python #exception #pyqt #qthread

#python #python-3.x #pyqt #pyqt5 #qt-designer

Вопрос:

Мое приложение PyQt больше не выводит ошибку (stderr?) на консоль.

Я использую QtDesigner и импортирую пользовательский интерфейс следующим образом:

 from PyQt5 import QtCore, QtGui, QtWidgets
import sys
from PyQt5.uic import loadUiType
Ui_MainWindow, QMainWindow = loadUiType("test.ui")

class Main(QMainWindow, Ui_MainWindow):
    """Main window"""
    def __init__(self,parent=None):
        super(Main, self).__init__(parent)
        self.setupUi(self)
        self.pushButton.clicked.connect(self.testfunc)

   def testfunc(self):
        print(9/0)

if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)
    main = Main()
    main.show()
    sys.exit(app.exec_())
  

test.ui содержит QPushButton и метку. Когда я вызываю testfunc (который, очевидно, выдает ошибку) в приложении, отличном от Qt, я получаю сообщение об ошибке, трассировку и т.д. Когда я выполняю этот код, он просто завершается.

Ранее я писал приложение PyQt без QtDesigner, и оно выводило ошибки на консоль, как и ожидалось. В чем разница с QtDesigner и наследованием?

Комментарии:

1. Вы устанавливали PyQt, используя предварительно скомпилированный двоичный файл, или вы скомпилировали его самостоятельно?

2. Я использовал этот предварительно скомбинированный 64-разрядный двоичный файл: riverbankcomputing.com/software/pyqt/download5

3. Я думаю, в этом проблема. У меня была та же проблема, поэтому я переустановил PyQt5 из исходных текстов, скомпилировав его с помощью mingw32, и теперь все работает.

4. У меня возникли проблемы с компиляцией, поэтому я просто откатился к более ранней версии (5.4.1 вместо 5.5.1). Это сделало свое дело. Сообщения об ошибках возвращаются, и я могу правильно отладить свое приложение. Спасибо!

5. @Jannis Как выполнить откат к предыдущей версии? Где их можно найти?

Ответ №1:

Вероятно, это связано с изменениями в способе обработки исключений в PyQt-5.5. Цитирую из документов PyQt5:

В PyQt версии 5.5 необработанное исключение Python приведет к вызову функции qFatal() Qt. По умолчанию это вызовет abort() и приложение завершит работу. Обратите внимание, что перехват исключений, установленный приложением, по-прежнему будет иметь приоритет.

Когда я запускаю ваш пример в обычной консоли, вот что я вижу:

 $ python test.py
Traceback (most recent call last):
  File "test.py", line 213, in testfunc
    print(9/0)
ZeroDivisionError: division by zero
Aborted (core dumped)
  

Итак, основное отличие заключается в том, что приложение теперь будет немедленно прерываться при обнаружении необработанного исключения (т. Е. Точно так же, как это сделал бы обычный скрипт на Python). Конечно, вы все еще можете контролировать это поведение с помощью try/except блока или глобально, переопределив sys.excepthook.

Если вы не видите никакой обратной трассировки, это может быть связано с проблемой с IDE Python, которую вы используете для запуска своего приложения.

PS:

Как минимум, старое поведение PyQt4, заключающееся в простой печати трассировки в stdout / stderr, может быть восстановлено следующим образом:

 def except_hook(cls, exception, traceback):
    sys.__excepthook__(cls, exception, traceback)

if __name__ == "__main__":

    import sys
    sys.excepthook = except_hook
  

Комментарии:

1. Спасибо за ответ! Да, когда я использовал блокировку try / except, приложение не завершилось. Я не думаю, что это проблема с IDE. Для теста без графического интерфейса у меня все еще была трассировка, и я попробовал это как с pycharm, так и с eclipse. И в более старой версии PyQt трассировка работает так, как я хочу. С PyQt5.5 все еще можно было бы увидеть обратную трассировку, если бы я запустил программу в «режиме отладки». Хотя это было действительно медленно. Как вы должны отлаживать приложение PyQt5.5 после последнего обновления?

2. @Jannis. Но это действительно звучит как проблема с этими IDE, не так ли? Как я показал в своем ответе, трассировка отображается при запуске вашего скрипта в консоли. Так почему ваши IDE не могут этого сделать? Я сам никогда не использовал IDE и всегда устанавливал excepthook в своих программах — так что для меня ничего особенного не изменилось, когда дело доходит до отладки.

3. Вы правы, я недостаточно внимательно прочитал ваш комментарий. Я переустановил PyQt5.5, чтобы проверить это. В консоли я получаю тот же вывод, что и вы. Однако как в pycharm, так и в eclipse трассировка не отображается. Они не показывают обратную трассировку с PyQt5.5, в то время как они показывают ее для PyQt5.4.1. Я не менял никаких промежуточных параметров. Скоро я рассмотрю возможность использования excepthooks. На данный момент я доволен обычной трассировкой.

4. Spyder также не показывает обратную трассировку. Это правильный способ справиться с таким поведением? gist.github.com/Winand/e98e3f2f073826b7c08b58fb6d338b51

5. @Winand. Вероятно, вам следует спросить разработчиков Spyder.

Ответ №2:

Я использовал модуль обратной трассировки python в сочетании с инструкцией try / except, чтобы убедиться, что обратная трассировка напечатана перед выходом:https://docs.python.org/3/library/traceback.html

Специально я использую трассировку.print_exc()