从控制台 (Ctrl-C) 终止时退出 PyQt 应用程序的正确方法是什么?

新手上路,请多包涵

从控制台 (Ctrl-C) 终止时退出 PyQt 应用程序的正确方法是什么?

目前(我没有做任何特别的事情来处理 unix 信号),我的 PyQt 应用程序忽略了 SIGINT (Ctrl+C)。我希望它表现良好并在它被杀死时退出。我该怎么做?

原文由 static_rtti 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.1k
2 个回答

17.4. signal — 设置异步事件的处理程序

尽管就 Python 用户而言,Python 信号处理程序是异步调用的,但它们只能发生在 Python 解释器的“原子”指令之间。这意味着在纯 C 实现的长时间计算(例如对大量文本的正则表达式匹配)期间到达的信号可能会延迟任意时间。

这意味着 Python 无法在 Qt 事件循环运行时处理信号。只有当 Python 解释器运行时(当 QApplication 退出时,或者当从 Qt 调用 Python 函数时)信号处理程序才会被调用。

一种解决方案是使用 QTimer 让解释器不时运行。

请注意,在下面的代码中,如果没有打开的窗口,应用程序将在消息框出现后退出,而不管用户的选择,因为 QApplication.quitOnLastWindowClosed() == True。这种行为是可以改变的。

 import signal
import sys

from PyQt4.QtCore import QTimer
from PyQt4.QtGui import QApplication, QMessageBox

# Your code here

def sigint_handler(*args):
    """Handler for the SIGINT signal."""
    sys.stderr.write('\r')
    if QMessageBox.question(None, '', "Are you sure you want to quit?",
                            QMessageBox.Yes | QMessageBox.No,
                            QMessageBox.No) == QMessageBox.Yes:
        QApplication.quit()

if __name__ == "__main__":
    signal.signal(signal.SIGINT, sigint_handler)
    app = QApplication(sys.argv)
    timer = QTimer()
    timer.start(500)  # You may change this if you wish.
    timer.timeout.connect(lambda: None)  # Let the interpreter run each 500 ms.
    # Your code here.
    sys.exit(app.exec_())

LinearOrbit 指出的 另一种可能的解决方案是 signal.signal(signal.SIGINT, signal.SIG_DFL) ,但它不允许自定义处理程序。

原文由 Artur Gaspar 发布,翻译遵循 CC BY-SA 4.0 许可协议

如果您只是希望让 ctrl-c 关闭应用程序 - 而不是“友好”/ 优雅- 然后从 http://www.mail-archive.com/pyqt@riverbankcomputing.com/msg13758.html ,您可以使用这个:

 import signal
signal.signal(signal.SIGINT, signal.SIG_DFL)

import sys
from PyQt4.QtCore import QCoreApplication
app = QCoreApplication(sys.argv)
app.exec_()

显然这适用于 Linux、Windows 和 OSX——到目前为止我只在 Linux 上测试过它(并且它有效)。

原文由 LinearOrbit 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
logo
Stack Overflow 翻译
子站问答
访问
宣传栏