web-dev-qa-db-ja.com

簡単なIPythonの例はsys.exit()で例外を発生させます

IPythonで非常に単純なPySide(およびPyQt)チュートリアルをいくつか実行しています。 1つのチュートリアルは、スロットと信号を示すためにいくつかのスライダーを備えたウィンドウを作成するだけです。

実行中のデモアプリケーションのウィンドウを閉じると、次のエラーが表示されます。

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の高速でインタラクティブな性質が失われます:(

11
MountainX

この回答は、ipython-usersメーリングリストのMatthias BUSSONNIERに感謝します。

実行中のデモアプリケーションのウィンドウを閉じると、次のエラーが表示されます。例外が発生しました。%tbを使用して完全なトレースバックを確認してください。 SystemExit:0

Pythonを終了せずにIPythonを実行しているため、sys.exit(0)を使用しないでください。

(実際の)コマンドラインからアプリを実行して戻りステータスを取得したい場合は、追加してください。

コードをもう一度実行しようとすると、次のようになります。
RuntimeError:QApplicationインスタンスはすでに存在しています。

これはPySideバグであり、バグとは見なされないため、「修正されません」。

参照 https://github.com/ipython/ipython/issues/1124
および http://bugs.pyside.org/show_bug.cgi?id=855

QApplicationは1つのインスタンスしか持つことができず、アプリを終了することは明らかにオブジェクトを削除するのに十分な理由とは見なされません...

上記の問題からこのコードを使用できます:

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

これは私の現在のニーズに対して十分な解決策でした。

25
MountainX

次のように、後でQApplicationを削除する必要があります。

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

このコードを使用すると、IPythonまたは他の任意の場所で何度でもアプリケーションを再実行でき、qtアプリケーションを閉じるたびに、オブジェクトはPythonで削除されます。

9
Ali B

sys.exitはインターパーターを終了するためにSystemExitをレイズするだけです。

ipythonはインタラクティブモードでスクリプトを実行するときにSysExitをキャッチするので、これは実際にはエラーではありませんが、ipythonの機能により、スクリプトが実行されたときにインタラクティブインタープリターがシャットダウンするのを回避できます。インタラクティブなセッションで欲しい。

4
mata

QApplicationのインスタンスがすでに存在するかどうかを確認してください。インスタンスがすでに実行されていて、新しいインスタンスを作成しようとしているときにエラーが発生するためです。

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