简单的IPython示例在sys.exit()上引发异常

Mou*_*inX 11 exception exit ipython pyqt4 pyside

我在IPython中做了一些非常简单的PySide(和PyQt)教程.一个教程只是创建一个带有一些滑块的窗口来演示插槽和信号.

当我关闭正在运行的演示应用程序的窗口时,我看到此错误:

An exception has occurred, use %tb to see the full traceback.
SystemExit: 0
To exit: use 'exit', 'quit', or Ctrl-D.
Run Code Online (Sandbox Code Playgroud)

所以我运行%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
Run Code Online (Sandbox Code Playgroud)

如果我再次尝试执行我的代码,我会得到这个:

RuntimeError: A QApplication instance already exists.
Run Code Online (Sandbox Code Playgroud)

如果它有帮助,这里我的代码:

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()
Run Code Online (Sandbox Code Playgroud)

使用python运行代码时没有错误:

python myexample.py
Run Code Online (Sandbox Code Playgroud)

当我在IPython(包括笔记本或qtconsole或常规ipython终端)中运行代码时,才会发生此错误.

更新:我的主要问题是我无法快速轻松地再次运行应用程序.如果我再次尝试运行我的代码,我会得到这个:

RuntimeError: A QApplication instance already exists.
Run Code Online (Sandbox Code Playgroud)

这杀死了IPython的快速,互动性:(

Mou*_*inX 25

这个答案要归功于来自ipython-users邮件列表的Matthias BUSSONNIER.

当我关闭正在运行的演示应用程序的窗口时,我看到此错误:发生了异常,使用%tb查看完整的回溯.SystemExit:0

只是不要使用sys.exit(0),因为你没有退出python,但仍然运行IPython.

如果您希望从(实际)命令行运行应用程序并具有返回状态,请将其添加回来.

如果我再次尝试执行我的代码,我会得到:
RuntimeError:QApplication实例已经存在.

这是一个他们"不会修复"的PySide Bug,因为他们认为它不是一个bug.

请参阅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)
Run Code Online (Sandbox Code Playgroud)

这是满足我目前需求的充分解决方案.


小智 9

您需要做的是使QApplication稍后被删除,如下所示:

app = QApplication(sys.argv)
app.aboutToQuit.connect(app.deleteLater)
Run Code Online (Sandbox Code Playgroud)

使用此代码,您可以在IPython中或其他任何地方重新运行应用程序,并且每次关闭qt应用程序时,都将在python中删除该对象.


mat*_*ata 5

sys.exit只是提出SystemExit终止interperter。

ipythonSysExit在交互模式下执行脚本时会捕获,因此这实际上不是错误,但是 ipython 的一个功能确实避免了在执行脚本时关闭交互式解释器,因为这不是您通常在交互式会话中想要的。


Par*_*oni 5

根据https://github.com/spyder-ide/spyder/issues/4639

\n\n

首先,检查实例是否已存在,然后分配该实例或创建一个新实例:

\n\n
if not QApplication.instance():\n    app = QApplication(sys.argv)\nelse:\n    app = QApplication.instance() \n
Run Code Online (Sandbox Code Playgroud)\n\n

(此片段摘自@NotSoBrainy 的答案。)

\n\n

然后,在该show()方法之后:

\n\n
QtWidgets.QApplication.setQuitOnLastWindowClosed(True)\napp.exec_()\napp.quit()\n
Run Code Online (Sandbox Code Playgroud)\n\n

\xe2\x80\x99s 不需要sys.exit().

\n\n

这解决了我的问题,这是完全相同的。

\n