Простой пример IPython вызывает исключение на sys.exit()

Я делаю несколько простых инструкций PySide (и PyQt) в IPython. Один учебник просто создает окно с некоторыми слайдерами для демонстрации слотов и сигналов.

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

An exception has occurred, use %tb to see the full traceback.
SystemExit: 0
To exit: use 'exit', 'quit', or Ctrl-D.

Итак, я запускаю% tb и получаю следующее:

SystemExit                                Traceback (most recent call last)
/Workspaces/scratch/<ipython-input-1-88966dcfb499> in <module>()
     33 
     34 if __name__ == "__main__":
---> 35     main()

/Workspaces/scratch/<ipython-input-1-88966dcfb499> in main()
     29         w.show()
     30         app.exec_()
---> 31         sys.exit(0)
     32 
     33 

SystemExit: 0

Если я снова попытаюсь выполнить мой код, я получаю следующее:

RuntimeError: A QApplication instance already exists.

В случае, если это помогает, вот мой код:

from PySide.QtCore import *
from PySide.QtGui import *
import sys

class MyWindow(QWidget):
    def __init__(self):
        QWidget.__init__(self, None)

        vbox = QVBoxLayout(self)

        self.slider1 = QSlider(Qt.Horizontal)
        self.slider1.setRange(0, 99)
        self.slider1.setValue(0)
        vbox.addWidget(self.slider1)

        self.slider2 = QSlider(Qt.Horizontal)
        self.slider2.setRange(0, 99)
        self.slider2.setValue(99)
        vbox.addWidget(self.slider2)

        self.slider1.valueChanged.connect(self.slider2Changed)

    def slider2Changed(self, position):
        self.slider2.setValue(self.slider2.maximum() - position)

def main():
        app = QApplication(sys.argv)
        w = MyWindow()
        w.show()
        app.exec_()
        sys.exit(0)

if __name__ == "__main__":
    main()

У меня нет ошибок при запуске кода с помощью python:

python myexample.py

Эта ошибка возникает только при запуске кода в IPython (включая ноутбук или qtconsole или обычный терминал ipython).

ОБНОВЛЕНИЕ: Моя основная проблема заключается в том, что я не могу запустить приложение снова и снова быстро и легко. Если я попытаюсь снова запустить свой код, я получаю следующее:

RuntimeError: A QApplication instance already exists.

Это убивает быстрый, интерактивный характер IPython: (

Ответ 1

Этот ответ получен благодаря Matthias BUSSONNIER из списка рассылки ipython-пользователей.

Когда я закрываю окно работающего демонстрационного приложения, я вижу эту ошибку: Произошло исключение, используйте% tb, чтобы увидеть полную трассировку. SystemExit: 0

Просто не используйте sys.exit(0), поскольку вы не выходите из python, но все еще выполняете IPython.

Добавьте его обратно, если вы хотите запустить приложение из (реальной) командной строки и иметь статус возврата.

Если я снова попытаюсь выполнить мой код, я получаю следующее:
RuntimeError: экземпляр QApplication уже существует.

Это ошибка PySide, которую они "не будут исправлять", поскольку они не считают ее ошибкой.

См. https://github.com/ipython/ipython/issues/1124)
и http://bugs.pyside.org/show_bug.cgi?id=855

QApplication может иметь только один экземпляр и выйти из приложения по-видимому, не считается достаточной достаточной причиной для удаления объект...

Вы можете использовать этот код из перечисленных выше проблем:

app=QtGui.QApplication.instance() # checks if QApplication already exists 
if not app: # create QApplication if it doesnt exist 
     app = QtGui.QApplication(sys.argv)

Это было достаточным решением для моих нынешних потребностей.

Ответ 2

Что вам нужно сделать, так это заставить QApplication быть удаленным позже, как в:

app = QApplication(sys.argv)
app.aboutToQuit.connect(app.deleteLater)

Используя этот код, вы можете повторно запускать приложение столько раз, сколько хотите в IPython или где-либо еще, и каждый раз, когда вы закрываете приложение qt, объект будет удален в python.

Ответ 3

sys.exit просто вызывает SystemExit, чтобы завершить интерпертер.

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

Ответ 4

Проверьте, присутствует ли уже экземпляр QApplication или нет, так как ошибка возникает, когда экземпляр уже запущен, и вы пытаетесь создать новый.

if not QtWidgets.QApplication.instance():
    app = QtWidgets.QApplication(sys.argv)
else:
    app = QtWidgets.QApplication.instance()