当我打印 pandas DataFrame 时,QMainWindow 意外关闭?
QMainWindow unexpectedly closes when I print a pandas DataFrame?
下面是重现此问题的最小示例。
from PyQt5 import QtWidgets
import pandas as pd
class PandasGUI(QtWidgets.QMainWindow):
def __init__(self):
super().__init__()
# This ensures there is always a reference to this widget and it doesn't get garbage collected
self._ref = self
inner = pd.DataFrame([3, 4, 5])
# Printing the DataFrame makes some windows close/disappear leaving only 3 QMainWindow windows
# Commenting out this print statement causes 5 windows to be shown as expected
print(inner)
self.show()
# Should create 5 PandasGUI windows
app = QtWidgets.QApplication([])
for i in range(5):
outer = pd.DataFrame([1, 2, 3])
PandasGUI()
app.exec_()
我遇到的问题是,当我 运行 此代码时,我显示的是 3 或 4 windows 而不是 5,我不明白为什么。
观察
- 如果我删除
self._ref = self
行并将小部件存储在持久列表对象中,我会得到 5 windows
- 如果我不创建
outer
DataFrame,我会得到 5 windows
- 如果我继承 QWidget 而不是 QMainWindow 我得到 5 windows
- 如果我在
__init__
中添加任何创建 Widget 的行,我会得到 5 windows,例如 x = QtWidgets.QPushButton()
- 我无法使用不同版本的 PyQt 和 pandas 一致地重现此内容
PyQt==5.13.0
pandas==0.24.2
我在两台不同的电脑上复制了这个。我觉得这是其中一个库的错误,但我想帮助理解这里的实际根本原因,因为我的示例需要这样一个特定的场景......它不会作为 GitHub 问题有用,我不甚至不知道哪个图书馆负责。
windows不确实是意料之外的。真正的错误在您自己的代码中。您正在 隐式地 创建随机保持对象活动的引用循环。 Python 的垃圾收集器不保证何时或以何种顺序删除对象,因此您看到的不可预知的行为是 "normal"。如果你在 for 循环后面加上 import gc; gc.collect()
,那么 windows 可能会全部被删除。因此,正确的解决方案是保留 explict 对 windows 的引用,正如您在第一个要点中提到的那样。
下面是重现此问题的最小示例。
from PyQt5 import QtWidgets
import pandas as pd
class PandasGUI(QtWidgets.QMainWindow):
def __init__(self):
super().__init__()
# This ensures there is always a reference to this widget and it doesn't get garbage collected
self._ref = self
inner = pd.DataFrame([3, 4, 5])
# Printing the DataFrame makes some windows close/disappear leaving only 3 QMainWindow windows
# Commenting out this print statement causes 5 windows to be shown as expected
print(inner)
self.show()
# Should create 5 PandasGUI windows
app = QtWidgets.QApplication([])
for i in range(5):
outer = pd.DataFrame([1, 2, 3])
PandasGUI()
app.exec_()
我遇到的问题是,当我 运行 此代码时,我显示的是 3 或 4 windows 而不是 5,我不明白为什么。
观察
- 如果我删除
self._ref = self
行并将小部件存储在持久列表对象中,我会得到 5 windows - 如果我不创建
outer
DataFrame,我会得到 5 windows - 如果我继承 QWidget 而不是 QMainWindow 我得到 5 windows
- 如果我在
__init__
中添加任何创建 Widget 的行,我会得到 5 windows,例如x = QtWidgets.QPushButton()
- 我无法使用不同版本的 PyQt 和 pandas 一致地重现此内容
PyQt==5.13.0
pandas==0.24.2
我在两台不同的电脑上复制了这个。我觉得这是其中一个库的错误,但我想帮助理解这里的实际根本原因,因为我的示例需要这样一个特定的场景......它不会作为 GitHub 问题有用,我不甚至不知道哪个图书馆负责。
windows不确实是意料之外的。真正的错误在您自己的代码中。您正在 隐式地 创建随机保持对象活动的引用循环。 Python 的垃圾收集器不保证何时或以何种顺序删除对象,因此您看到的不可预知的行为是 "normal"。如果你在 for 循环后面加上 import gc; gc.collect()
,那么 windows 可能会全部被删除。因此,正确的解决方案是保留 explict 对 windows 的引用,正如您在第一个要点中提到的那样。