如何在PySide/PyQt中终止纯控制台应用程序?

2 投票
1 回答
3357 浏览
提问于 2025-04-18 14:57

我正在尝试把一段来自Summerfield文章中关于旧版PyQt信号和槽的代码转换成新版的PySide代码。其中一个例子是一个纯控制台应用程序,我之前从未接触过。不幸的是,当我尝试多次运行它时,系统告诉我之前的应用程序仍在运行。

这个应用程序很简单:基本上就是让你设置一个数字,并反馈这个数字是否是新的:

from PySide import QtCore
import sys

class TaxRate(QtCore.QObject):
    rateChangedSig=QtCore.Signal(float)

    def __init__(self):
        QtCore.QObject.__init__(self)
        self.rate = 17.5

    def getRate(self):
        return self.rate

    def setRate(self, newRate):
        if newRate != self.rate:
            self.rate = newRate
            self.rateChangedSig.emit(self.rate)  #was self.emit(SIGNAL("rateChanged"), self.rate)

@QtCore.Slot() #technically not really needed
def rateChangedSlot(value):
    print("Tax rate changed to {0:.2f} %".format(value))


if __name__=="__main__":
    qtApp = QtCore.QCoreApplication(sys.argv)  #origional had QtGui.QApplication, but there is no GUI
    vat = TaxRate()
    vat.rateChangedSig.connect(rateChangedSlot) #was vat.connect(vat, SIGNAL("rateChanged"), rateChanged)
    vat.setRate(8.5)     # A change will occur (new rate is different)

    qtApp.quit() 
    sys.exit(qtApp.exec_())

总体来说,它的运行效果如预期,但最后两行代码并没有结束进程。当我尝试运行这个程序两次时,第二次我的IDE(Spyder)总是告诉我它已经在一个单独的进程中运行。如果我从命令行运行它,窗口就会卡住。

奇怪的是,当我注释掉最后两行时,就不会出现这个警告。这与我之前对PySide GUI应用程序和quit()文档的理解正好相反。

根据Zetcode的关闭窗口示例,我尝试把qtApp.quit()替换成qtApp.instance().quit(),结果还是没有结束进程。

那么,我该如何结束这个进程呢?

一个想法是我根本不应该启动它(这里有建议)。尽管这是一个纯控制台应用程序,Summerfield的原始程序是用app=QtGui.QApplication(sys.argv)初始化的,并且没有最后两行代码。多次运行时一切正常。然而,难道不是应该担心每次运行都会创建一个新进程吗?所以他的程序似乎在没有警告的情况下有效地增加了进程数量?(不过在我的系统上似乎并没有发生这种情况,所以答案似乎是'不',但我不太明白原因)。

使用PySide控制/初始化/结束一个控制台应用程序的正确方法是什么?

(暂时不讨论为什么有人会在Python中使用PySide来做一个纯控制台应用程序,之前有人提到过这个问题。但如果有人对此感兴趣,我可以单独提出一个问题)。


可能相关的帖子:

1 个回答

3

问题出在你在调用 QCoreApplication.exec_() 之前就调用了 QCoreApplication.quit()。调用 quit 是立即执行的,而不是等到事件循环中去处理。调用 QCoreApplication.exec_() 是启动事件循环的,这个循环会一直运行,直到你在它运行的时候调用 QCoreApplication.exit()(或者 QCoreApplication.quit())来结束它。

这个问题在 Qt的文档中 有部分解释,但很容易被忽略。

我想你现在的代码中其实不需要调用 exec_(),因为你没有使用任何事件(大多数事件是和窗口、鼠标、键盘相关的,不过将来你可能会用到一些,比如 QTimer 生成的事件)。这真的取决于你将来想用这个程序做什么。如果你不调用 exec_(),那么你的脚本就会像普通的Python脚本那样退出(你代码中唯一会阻止它退出的函数就是 exec_(),如果去掉它,脚本就不会继续运行了)。

撰写回答