如何在PySide/PyQt中终止纯控制台应用程序?
我正在尝试把一段来自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 个回答
问题出在你在调用 QCoreApplication.exec_()
之前就调用了 QCoreApplication.quit()
。调用 quit
是立即执行的,而不是等到事件循环中去处理。调用 QCoreApplication.exec_()
是启动事件循环的,这个循环会一直运行,直到你在它运行的时候调用 QCoreApplication.exit()
(或者 QCoreApplication.quit()
)来结束它。
这个问题在 Qt的文档中 有部分解释,但很容易被忽略。
我想你现在的代码中其实不需要调用 exec_()
,因为你没有使用任何事件(大多数事件是和窗口、鼠标、键盘相关的,不过将来你可能会用到一些,比如 QTimer
生成的事件)。这真的取决于你将来想用这个程序做什么。如果你不调用 exec_()
,那么你的脚本就会像普通的Python脚本那样退出(你代码中唯一会阻止它退出的函数就是 exec_()
,如果去掉它,脚本就不会继续运行了)。