gpt4 book ai didi

python - 多个 PyQt5.QtWidgets.QApplication 对象的段错误

转载 作者:行者123 更新时间:2023-12-01 00:33:41 25 4
gpt4 key购买 nike

有人可以向我解释一下,如果在下面的代码中我在每次调用 QApplication 构造函数之间删除 del app ,为什么会出现段错误?同样,将 QApplication 对象分配给具有不同名称的变量(例如 app_1、app_2、app_3)可以避免段错误。

from PyQt5.QtWidgets import (QApplication, QMessageBox)
import sys

if __name__ == '__main__':
app = QApplication(sys.argv)
msg = QMessageBox()
msg.setText('Message Box 1')
msg.show()
app.exit(app.exec())
del app # Why is this necessary to avoid a segmentation fault?

app = QApplication(sys.argv)
msg = QMessageBox()
msg.setText('Message Box 2')
msg.show()
app.exit(app.exec())
del app # Why is this necessary to avoid a segmentation fault?

app = QApplication(sys.argv)
msg = QMessageBox()
msg.setText('Message Box 3')
msg.show()
app.exit(app.exec())

澄清:我对“修复”此代码不感兴趣。我正在尝试理解这种行为。

最佳答案

这个问题更多地与 C++ 相关,而不是与 Python 相关。

应考虑以下因素:

  • QApplication 是一个单例,因此整个应用程序可以使用 instance() 方法访问它。

  • 当调用exit()方法时,它不会消除对象,只是停止处理事件。

因此,当您创建另一个 QApplication 而不删除前一个 QApplication 时,不会创建该实例,因此 instance() 为 nullptr:

import sys
from PyQt5.QtWidgets import QApplication, QMessageBox

if __name__ == "__main__":
app = QApplication(sys.argv)
print(f"app: {app}, instance: {QApplication.instance()}")
msg = QMessageBox()
msg.setText("Message Box 1")
msg.show()
app.exit(app.exec())
app = QApplication(sys.argv)
print(f"app: {app}, instance: {QApplication.instance()}")

输出:

app: <PyQt5.QtWidgets.QApplication object at 0x7effbd41ea50>, instance: <PyQt5.QtWidgets.QApplication object at 0x7effbd41ea50>
app: <PyQt5.QtWidgets.QApplication object at 0x7effbd41eb90>, instance: None

因此,在使用 setText() 设置文本时,使用了一个信号,该信号通过 QXApplication 使用 instance() 方法使用事件循环,正如我们所见,nullptr 生成了段错误。

如果为 QXApplication 使用其他名称,事件循环将访问另一个不是 None (nullptr) 的 instance()

import sys
from PyQt5.QtWidgets import QApplication, QMessageBox

if __name__ == "__main__":
app1 = QApplication(sys.argv)
print(f"app: {app1}, instance: {QApplication.instance()}")
msg = QMessageBox()
msg.setText("Message Box 1")
msg.show()
app1.exit(app1.exec())
app2 = QApplication(sys.argv)
print(f"app: {app2}, instance: {QApplication.instance()}")
msg = QMessageBox()
msg.setText("Message Box 1")
msg.show()
app2.exit(app2.exec())

输出:

app: <PyQt5.QtWidgets.QApplication object at 0x7f3462720a50>, instance: <PyQt5.QtWidgets.QApplication object at 0x7f3462720a50>
app: <PyQt5.QtWidgets.QApplication object at 0x7f3462720b90>, instance: <PyQt5.QtWidgets.QApplication object at 0x7f3462720b90>
<小时/>

总之,如果你不使用 del 那么 instance() 它将是 None,但是如果你使用它,它将被称为 C++ 中对象的析构函数,消除 instance() 返回的内存,允许创建一个新对象。

<小时/>

正如 @ekhumoro 所说:

It's the exact order of deletion that really matters. Without del, the new QApplication is created before the old one is deleted (so the old instance() doesn't get replaced). But then the app variable is immediately reassigned, which implictly deletes the old application, making instance() return None.

关于python - 多个 PyQt5.QtWidgets.QApplication 对象的段错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57978839/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com