Reputation: 5428
Below is a minimal example that reproduces this problem.
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_()
The problem I have is when I run this code I get 3 or 4 windows shown instead of 5, and I cannot figure out why.
Observations
self._ref = self
line and instead store the widgets in a persistent list object I get 5 windowsouter
DataFrame I get 5 windows__init__
that creates a Widget I get 5 windows, such as x = QtWidgets.QPushButton()
PyQt==5.13.0
pandas==0.24.2
I reproduced this on two different computers. I have a feeling this is a bug with one of the libraries but would like help understanding the actual root cause here since my example requires such a specific scenario... it would not be useful as a GitHub issue and I don't even know which library is responsible.
Upvotes: 0
Views: 86
Reputation: 120718
It is actually unexpected that the windows don't close. The real bug is in your own code. You are implicitly creating reference-cycles which are randomly keeping objects alive. Python's garbage-collector does not guarantee when or in what order objects will be deleted, so the unpredictable behaviour you see is "normal". If you add import gc; gc.collect()
after the for-loop, the windows will probably all be deleted. So the correct solution is to keep explict references to the windows, as you already mentioned in your first bullet-point.
Upvotes: 1