0

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

  • If I remove the self._ref = self line and instead store the widgets in a persistent list object I get 5 windows
  • If I don't create the outer DataFrame I get 5 windows
  • If I inherit a QWidget instead of a QMainWindow I get 5 windows
  • If I add any line inside __init__ that creates a Widget I get 5 windows, such as x = QtWidgets.QPushButton()
  • I cannot reproduce this consistently with different versions of PyQt and pandas other than those below

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.

pyjamas
  • 4,608
  • 5
  • 38
  • 70
  • 2
    If you remove the dataframe then the problem persists? I can't reproduce what you say. How are you running your script? Are you using any IDE ?, etc. – eyllanesc Aug 17 '19 at 23:00
  • @eyllanesc Ok I retract my comment I made earlier, I don't think it's caused by PyCharm. I was able to reproduce it without any IDE on both computers. I am on Windows 10. Here's a video of it: https://www.screencast.com/t/Ur7LIeJ8JQWZ – pyjamas Aug 17 '19 at 23:23
  • @ekhumoro Thank you, that explains it. I misunderstood how gc works with self references. If you copy paste that into an answer I'll accept it to close this. – pyjamas Aug 25 '19 at 23:37

1 Answers1

1

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.

ekhumoro
  • 115,249
  • 20
  • 229
  • 336