Skip to content
This repository has been archived by the owner on Aug 2, 2023. It is now read-only.

QT5 Threads not captured in the debugger via VSCode #428

Closed
d3r3kk opened this issue May 22, 2018 · 12 comments
Closed

QT5 Threads not captured in the debugger via VSCode #428

d3r3kk opened this issue May 22, 2018 · 12 comments
Assignees
Milestone

Comments

@d3r3kk
Copy link
Contributor

d3r3kk commented May 22, 2018

We have an issue reported against microsoft/vscode-python#176 where the user reports that our debugger won't stop on a breakpoint within a QTThread process.

Reproduction steps

Ensure VSCode is installed/updated and the vscode-python extension is installed/updated as well.

> mkdir pyQtThreadTest
> cd pyQtThreadTest
> python -m venv venv
> venv/scripts/activate
> pip install PyQt5
> code .

In VSCode, ensure the latest Python extension is installed.

Create a new file called 'qt_thread_test.py' and copy/paste the following code into it:

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

Then, highlight add a breakpoint at line 16 in the qt_thread_test.py file and run the debugger by hitting F5. Once the window opens click the button to get the code to run and hit your breakpoint.

Expected Behaviour

The breakpoint is hit and execution stops on the breakpoint set.

Observed Behaviour

The breakpoint is ignored and execution runs without being stopped.

EDIT: Remove idea of attached file and just put the python code for repro inline.
EDIT: Change from highlighting line 16 to adding a breakpoint.
EDIT: Added instruction to click the app window's button.

@int19h
Copy link
Contributor

int19h commented May 22, 2018

To clarify, are they using the experimental debugger? The old one never supported this at all.

@d3r3kk
Copy link
Contributor Author

d3r3kk commented May 22, 2018

@int19h Yes, they are and if you do the repro you will see it fails to break on the breakpoint when using both debuggers.

@fabioz
Copy link
Contributor

fabioz commented May 23, 2018

I tested this inside the pydevd master version (without ptvsd) and it works properly.

-- note: you need to press the button for the thread to be run in the example (this is in the original report but not here).

Not sure what was the last sync pydevd -> ptvsd... I see there's a pull request open: #426 (so, maybe just applying it could fix the issue).

@d3r3kk
Copy link
Contributor Author

d3r3kk commented May 23, 2018

Updated instructions to be clearer, thanks.

Will wait to see if the next version fixes the problem then.

@fabioz
Copy link
Contributor

fabioz commented May 23, 2018

Actually, I took a better look and it seems that ptvsd is not passing the flag to enable qt support.

i.e.: pydevd doesn't monkey-patch qt modules by default, it requires a --qt-support=xxx, where xxx is one of: none, auto, pyqt5, pyqt4 or pyside.

@DonJayamanne
Copy link
Contributor

Created an issue #435, I believe that should fix this issue.

@DonJayamanne
Copy link
Contributor

DonJayamanne commented May 25, 2018

@fabioz If this is working, then does this mean auto is the default behavior, even though the --qt-support option isn't being passed into pydevd?

@d3r3kk
I've tested this at my end using the experimental debugger and it works as expected (on a Mac).
pyqt

@fabioz
Copy link
Contributor

fabioz commented May 28, 2018

@DonJayamanne no, the default is having it disabled if --qt-support is not passed.

I've gotten the latest release (2018.4.0) and on Linux I can't get it to work as you're getting there, although it works if I add the code below to the start of the module:

from _pydev_bundle import pydev_monkey_qt
pydev_monkey_qt.patch_qt('auto')

(which is what passing --qt-support=auto would do).

So not sure why it's working on your machine... is it possible you have some local change or you're using the development version and this is already fixed there?

@Gazoo101
Copy link

Just thought I'd chime in an say that I'm seeing the same issue with using PySide2 (aka Qt for Python) with Python 3 and the latest Vs Code.

Any breakpoint I set in code executed via the overwritten run method is never hit:

class WorkerThread(QtCore.QThread):

   def __init__(self, workFunc, parent = None):
      QtCore.QThread.__init__(self, parent)
      self.workFunc = workFunc

   # According to the wise Qt sages - do not call run() directly.
   # Instead commence execution via the start() function

   def run(self):
      self.workFunc()

Even a breakpoint on the self.workFunc() line is never hit.

@karthiknadig karthiknadig self-assigned this Jun 18, 2018
@karthiknadig karthiknadig added this to the June 2018.2 milestone Jun 18, 2018
@KestutisMa
Copy link

KestutisMa commented Mar 23, 2019

I also can't get breakpoint hit inside QThread run() method, 1.32.3 (2019-03-14) version of vscode, linux, pyqt5. Does anybody succeeded doing this?

@karthiknadig
Copy link
Member

@KestutisMa import ptvsd and add this to the thread function, ptvsd.debug_this_thread().
#1189 (comment)

@KestutisMa
Copy link

Thanks! ;-) probably it would be useful to add that in Python extension documentation or tutorial.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants