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()
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.