2016-06-24 2 views
4

Я разрабатываю научное приложение с использованием PyQt4 в течение нескольких недель и решил перейти на PyQt5. Помимо нескольких вещей, чтобы сгладить одно, меня озадачивает, и я не уверен, что его намеренное поведение или нет.Приложение PyQt5 выходит на ошибку, где приложение PyQt4 не будет

При использовании PyQt4: , если у меня была ошибка питона (AttributeError, FileNotFoundError или любой другой) сообщение об ошибке будет выведено на консоль питона, но я мог бы продолжать использовать приложение с графическим интерфейсом PyQt4

При использовании PyQt5, когда у меня ошибка python, все приложение закрывается на меня. Является ли это настройкой, или это намеченное поведение? Это потенциально катастрофично, как раньше, если бы была ошибка, я мог бы сохранить данные, которые я приобрел, но теперь приложение будет просто закрываться без предупреждения.

Вот пример, демонстрирующий поведение. Этот скрипт открывает виджет с кнопкой, которая активирует диалог файла. Если выбран действительный файл, код будет печатать объект filepointer в командной строке. Если ни один файл не выбран, потому что пользователь нажимает на отмену, тогда этот случай не обрабатывается, и python пытается открыть файл с помощью пути ''. В этом как PyQt4 и PyQt5 версии бросить ту же ошибку питона:

FileNotFoundError: [Errno 2] No such file or directory: '' 

Однако версия PyQt4 оставит виджет открытым, и пользователь может продолжать, в то время как версия PyQt5 закрывается, с выходным кодом 1.

Вот пример кода, выполненный: «питона script.py»

import sys 
# from PyQt4 import QtGui as qt 
# from PyQt4.QtCore import PYQT_VERSION_STR 
from PyQt5 import QtWidgets as qt 
from PyQt5.QtCore import PYQT_VERSION_STR 

def open_a_file(): 
    fname = qt.QFileDialog.getOpenFileName() 
    if PYQT_VERSION_STR[0] == '4': 
     f = open(fname, 'r') 
     print(f) 
    else: 
     f = open(fname[0], 'r') 
     print(f) 
    f.close() 

if __name__ == '__main__': 
    app = qt.QApplication(sys.argv) 

    w = qt.QWidget() 
    w.resize(250, 150) 
    w.move(300, 300) 
    w.setWindowTitle('PyQt 4 v 5') 
    btn = qt.QPushButton("Open a file", w) 
    btn.clicked.connect(open_a_file) 
    w.show() 

    sys.exit(app.exec_()) 

Могу ли я использовать PyQt5, но не врезаться так, что версия PyQt4 делает?

Вот моя текущая информационная система информационной системы:
для Windows 7 64-бит
Anaconda, Python 3.5
PyQt4 -> из источников Конда
PyQt5 -> Использование:

conda install --channel https://conda.anaconda.org/m-labs qt5 
conda install --channel https://conda.anaconda.org/m-labs pyqt5 

оба PyQt4 и PyQt5 установлены рядом друг с другом

+0

У вас есть исключенные исключения: они должны всегда прерывать программу. Если вы хотите их поймать, вам на это нужно. Поведение от PyQt4 было неправильным. Когда вы запускаете какую-либо программу Python, и есть неперехваченное исключение, оно прерывается. PyQt не предназначен для изменения чего-то такого фундаментального. –

+0

Я думаю, что «неправильно», вероятно, зависит от вашей перспективы.Как кто-то, кто координирует python, чтобы помочь в исследовании, а не развертывать корпоративные приложения, я считаю, что поведение PyQt4 гораздо более поддается моим целям, а именно: делать все хорошо и быстро, но не подвержено риску потери данных, а не с чрезмерно строгими соблюдение конвенций и парадигм кодирования, когда такая приверженность занимает больше времени, чем у меня. –

+0

Выньте 'PyQt4' и Python по умолчанию будет прерван на исключениях. Вот что вы должны ожидать. Если вы хотите изменить это, это на вас: уловки исключений легко. Вы должны быть четко о том, что вы хотите здесь; Изменение PyQt4 было неправильным, потому что это заставило вас думать (ошибочно!), Что это его задача сделать такое изменение. Это не. Это твоя работа. Единственная причина, по которой вы считаете, что это не ваша работа, - это глупая ошибка, которую имел дизайн PyQt4. Существование этого самого вопроса является следствием этой ошибки и подчеркивает, насколько это было неправильно./shiver –

ответ

4

Старое поведение может быть принудительно вызвано этим кодом, который я нашел после большего поиска. Я не уверен, что понимаю, почему это плохое поведение, которое должно быть устаревшим, но это действительно работает.

Я утверждаю, что это не должно быть поведение по умолчанию, и правильное использование исключений - это правильный способ программирования, но с учетом конкретной цели моего программирования и ограничений по времени я считаю полезным иметь доступ к как дополнительный режим, поскольку я все еще вижу трассировки исключений python, напечатанные на консоли, и не потеряет несохраненные данные из-за неперехваченного исключения.

import sys 

def my_excepthook(type, value, tback): 
    # log the exception here 

    # then call the default handler 
    sys.__excepthook__(type, value, tback) 

sys.excepthook = my_excepthook 
+0

По причинам @ kuba-ober, упомянутым выше - молчащие ошибки скрытия - это плохая идея, и по умолчанию это делает Python (и почти любой другой язык программирования с исключениями). (отказ от ответственности: я изначально предложил изменение) –

+0

@ TheCompiler, пока вы правы, на начальной стадии разработки могут быть случаи, когда вы хотите оставить некоторые исключения необработанными при реализации других функций (и вернуться к ним позже) без прямого сбоя программы, но просто записывая их (в stderr, в файл, в диалог, ...). В то время как обезьяна-патч 'sys.excepthook', похоже,« работает », я бы очень предпочел способ перехватить необработанные исключения, переопределяя/переопределяя метод в экземпляре' QApplication'. ([reimplementing 'notify'] (http://stackoverflow.com/a/19015654/794539) не предотвращает крах) – blubberdiblub

+0

Также см .: [этот ответ] (https://stackoverflow.com/a/37837374/ 4720018) – Dennis

Смежные вопросы