0

I learned from Debugging a pyQT4 app? how to be able to avoid the

QCoreApplication::exec: The event loop is already running

when running a PyQt5 application and using breakpoints. This works fine for doing prints to the console, but I still have trouble if I want to run matplotlib plt.show() during that breakpoint. Then I get the message above and just an empty figure.

Any idea how to overcome that?

Solved: replace plt.show() with plt.pause(0.01). Thank you @jared.

Below is a full example code. The breakpoint is triggered by pushing the button and I have commented under the breakpoint what I am typing on the console to get the empty figure.

import sys

from PyQt5 import QtWidgets
from PyQt5.QtWidgets import (
    QMainWindow, QWidget, QHBoxLayout, QPushButton, QLabel
    )

class MainWindow(QMainWindow):
    """Class main window."""

    def __init__(self):
        super().__init__()

        self.setWindowTitle('test')
        self.widget = QWidget()

        box = QHBoxLayout()
        self.widget.setLayout(box)
        self.lbl = QLabel('Hello')
        box.addWidget(self.lbl)

        self.btn = QPushButton('Push to breakpoint')
        box.addWidget(self.btn)
        self.btn.clicked.connect(self.run_script1)

        self.setCentralWidget(self.widget)

    def run_script1(self):
        breakpoint()
        #import matplotlib.pyplot as plt
        #plt.plot([1,2,3])
        #plt.show() / should be: plt.pause(0.01)

    def exit_app(self):
        """Exit app by menu."""
        sys.exit()

def prepare_debug():
    """Set a tracepoint in PDB that works with Qt."""
    # https://stackoverflow.com/questions/1736015/debugging-a-pyqt4-app
    from PyQt5.QtCore import pyqtRemoveInputHook
    import pdb
    pyqtRemoveInputHook()
    # set up the debugger
    debugger = pdb.Pdb()
    debugger.reset()
    # custom next to get outside of function scope
    debugger.do_next(None)  # run the next command
    users_frame = sys._getframe().f_back  # frame where user invoked `pyqt_set_trace()`
    debugger.interaction(users_frame, None)

if __name__ == '__main__':
    prepare_debug()
    app = QtWidgets.QApplication(sys.argv)
    w = MainWindow()
    w.show()
    app.exec()
jared
  • 4,165
  • 1
  • 8
  • 31
  • If you use `plt.pause(0.01)` instead, does that show the figure? – jared Jun 28 '23 at 20:12
  • `breakpoint()` blocks the event loop, which is a bad thing to do for UI toolkits, since it prevents them to properly draw their contents. Besides, why do you need the breakpoint for? In any case, if you want to use PyQt along with matplotlib, you should use FigureCanvas, not pyplot. – musicamante Jun 28 '23 at 21:04
  • Ah wonderful, @jared, that did the trick. Thanks! – EllenWasbo Jun 28 '23 at 21:26
  • @musicamante - I do use FigureCanvas in my application, but during debugging and and testing/exploring code I would like to use matplotlib.pyplot to have plots and images pop up without having the references to the specific canvases I have in my code. – EllenWasbo Jun 28 '23 at 21:29

1 Answers1

0

While debugging, if you want to show a pyplot figure, you can use the plt.pause(0.01) command (the time doesn't really matter). As per the documentation,

If there is an active figure, it will be updated and displayed before the pause, and the GUI event loop (if any) will run during the pause.

If you're interested in understanding the difference between pause and show, the documentation includes the links to their source code. For convenience, I have included those links below.

jared
  • 4,165
  • 1
  • 8
  • 31
  • @EllenWasbo Sure thing. If you consider your question answered then you can accept this answer (hit the gray check next to the answer to make it a green check). – jared Jun 29 '23 at 07:55