How to debug PyQt5 threads in Visual Studio Code?
Asked Answered
F

2

6

I am right now developing a PyQT5 application an use multithreading to avoid freezing of the GUI. Unfortuneately the Visual Studio Code debugger does not stop on breakpoints inside the executed thread. I tried all suggestions from the following page without fixing the problem. https://github.com/microsoft/ptvsd/issues/428. I think VS Code switched debugger from ptvsd to debugpy so all the suggestions do not hold any more. Maybe somebody has an idea how to fix this issue.

import time
import sys

from PyQt5.QtCore import QObject, QThread, pyqtSignal, pyqtSlot
from PyQt5.QtWidgets import QApplication, QPushButton, QTextEdit, QVBoxLayout, QWidget, QLabel


class Worker(QObject):
    sig_msg = pyqtSignal(str)  # message to be shown to user

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

    @pyqtSlot()
    def work(self):
        self.sig_msg.emit('Hello from inside the thread!')

        result = 1 + 1
        result2 = 1 + 2


class MyWidget(QWidget):

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

        self.setWindowTitle("Thread Example")

        form_layout = QVBoxLayout()

        self.setLayout(form_layout)
        self.resize(400, 200)

        self.button_start_threads = QPushButton("Start")
        self.button_start_threads.clicked.connect(self.start_threads)

        self.label = QLabel()

        form_layout.addWidget(self.label)
        form_layout.addWidget(self.button_start_threads)

        QThread.currentThread().setObjectName('main')

        self.__threads = None

    def start_threads(self):
        self.__threads = []

        worker = Worker()
        thread = QThread()
        thread.setObjectName('thread')
        self.__threads.append((thread, worker))  # need to store worker too otherwise will be gc'd
        worker.moveToThread(thread)

        worker.sig_msg.connect(self.label.setText)

        thread.started.connect(worker.work)
        thread.start() 


if __name__ == "__main__":
    app = QApplication([])

    form = MyWidget()
    form.show()

    sys.exit(app.exec_())

You can reproduce the error by setting a breakpoint at self.sig_msg.emit('Hello from inside the thrad!') in my case the debugger does not stop at this position. I use VS Code Version 1.65.2. The code is taken from the post mentioned above.

Frere answered 11/4, 2022 at 20:58 Comment(0)
K
15

I have recently experienced the same issue with VS Code and PyQt5. Following the advice at https://code.visualstudio.com/docs/python/debugging#_troubleshooting, I was able to hit the breakpoint in your example code by importing debugpy and adding debugpy.debug_this_thread() in the work method e.g.

def work(self):
    debugpy.debug_this_thread()
    self.sig_msg.emit('Hello from inside the thread!')

    result = 1 + 1
    result2 = 1 + 2

Hopefully that can help others facing the same issue.

Kalidasa answered 2/6, 2022 at 6:9 Comment(1)
For QThread - just to make it explicit: the call to 'debugpy.debug_this_thread()' must be made at the start of the thread run() where you have placed a break point.Reluctance
J
4

With the Python extension installed (the one made by Microsoft) there is an option to enable support of Qt. Witch enables thread debugging. I found this option by going through debugpy source code.

You can add "qt" option to launch.json. For example:

{
    "name": "Python Debugger: custom debugpy",
    "type": "debugpy",
    "request": "launch",
    "program": "main.py",
    "console": "integratedTerminal",
    "qt": "pyqt5"
}

Supported options are 'auto', 'pyside', 'pyside2', 'pyqt4' and 'pyqt5'. It does not seem to work with PyQt6 for now.

Jarvey answered 28/6 at 21:36 Comment(3)
Thank you, it worked. "qt": "pyside2" in my case. The editor highlights this as an unknown option but it does work!Individual
How do you enable support of Qt? Do you mean installing "Qt for Python" extension? If you were more specific about the "option in VS Code to enable support of Qt", I would vote for this answer becoming the accepted one. Btw, your solution works but slaps me with a lot of tracemalloc warnings.Ceiling
@RadekD I tried to clarify things, see the updated answer.Jarvey

© 2022 - 2024 — McMap. All rights reserved.