Qt Forum

    • Login
    • Search
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search
    • Unsolved

    Forum Updated on Feb 6th

    Solved Emit is delayed

    Qt for Python
    2
    3
    175
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • S
      sheepdog last edited by

      I have a program written in python that has a QT interface. I am using python 3's threading library and time.sleep and getting the following errors:

      • QBasicTimer::start: QBasicTimer can only be used with threads started with QThread
      • QBasicTimer::start: QBasicTimer can only be used with threads started with QThread
      • QBasicTimer::start: QBasicTimer can only be used with threads started with QThread
      • QBasicTimer::start: QBasicTimer can only be used with threads started with QThread

      In order to address this error I tried to define a QThread class to substitute. But the signal I am emitting does not connect to the receiver and only executes as the thread is exiting. This signal should be emit with each iteration of the loop in get_web_query, but instead it only appears when the get_web_query function exits. Please advise.

      #!/usr/bin/python3
      #WebQueryModule.py
      
      import sys, os, time, inspect
      sys.path.insert(0, '../')
      
      import web_query, search
      
      from PyQt5.QtWidgets import QApplication
      from PyQt5.QtCore import pyqtSignal, pyqtSlot, QThread
      
      class WebQueryThread(QThread):
          done_signal = pyqtSignal(str)
      
          def __init__(self):
              QThread.__init__(self)
      
          def run(self):
              self.search_web_query()
              self.done_signal.emit('WebQueryThread done_signal')
      
          def search_web_query(self):
              name = inspect.currentframe().f_code.co_name
              print(name)
              try:
                  if web_query.INTERTHREAD_SIGNAL:
                      web_query.main()
              except Exception as e:
                  print(sys.exc_info())
      
      class WebQueryResultThread(QThread):
          new_web_output = pyqtSignal(list)
      
          def __init__(self):
              QThread.__init__(self)
      
          def run(self):
              self.new_web_output.emit(['test','testing'])
              self.get_web_query()
      
          def new_web_query_output(self):
              name = inspect.currentframe().f_code.co_name
              new_web_query_output = next(web_query.get_output()).split('\n')
              return new_web_query_output
      
          def get_web_query(self):
              name = inspect.currentframe().f_code.co_name
              while web_query.INTERTHREAD_SIGNAL:
                  o = self.new_web_query_output()
                  print(name, o)
                  self.new_web_output.emit(o)
                  time.sleep(1)
              print('Exiting get_web_query')
      
      def process_done_signal(result):
              print(result)
              sys.exit()
      
      @pyqtSlot()
      def process_new_web_output(output):
          print('new web output')
      #    MyMainWindow.web_query_handler(output)
      
      if __name__ == '__main__':
          app = QApplication(sys.argv)
      
          thread = WebQueryThread()
          thread.done_signal.connect(process_done_signal)
          thread.start()
          thread2 = WebQueryResultThread()
          thread2.new_web_output.connect(process_new_web_output)
          thread2.start()
      
          time.sleep(5)
      
          # This will continue to run forever, except we are killing the app
          # in the process_done_signal() function.
      
          print('Signal to close...')
          web_query.INTERTHREAD_SIGNAL = False
      
          sys.exit(app.exec_())
      

      Output looks like this:

      get_web_query ['']
      Exiting get_web_query
      search_web_query
      main doing search
      get_web_query ['search_term: abwenden', '']
      Exiting get_web_query
      get_web_query ['search_term: abwenden', 'Translating: abwenden', 'sich [ von jdm / etw ] abwenden to turn away [ from sb / sth ] ', '']
      Exiting get_web_query
      get_web_query ['search_term: abwenden', 'Translating: abwenden', 'sich [ von jdm / etw ] abwenden to turn away [ from sb / sth ] ', '']
      Exiting get_web_query
      get_web_query ['search_term: abwenden', 'Translating: abwenden', 'sich [ von jdm / etw ] abwenden to turn away [ from sb / sth ] ', '']
      Exiting get_web_query
      Signal to close...
      new web output
      new web output
      new web output
      new web output
      new web output
      new web output

      Exiting web_query.main
      WebQueryThread done_signal

      1 Reply Last reply Reply Quote 0
      • jeremy_k
        jeremy_k last edited by

        The issue lies between the connection type (defaulted to AutoConnection in PyQt - https://www.riverbankcomputing.com/static/Docs/PyQt5/signals_slots.html?highlight=Qt.AutoConnection), and the sleep(5) between starting the threads, and invoking app.exec_(). Removing the sleep to allow the main thread's event loop to process the metacall events might result in interleaved output. That's up to the thread scheduler.

        Switching to DirectConnection will definitely interleave output. This might not be appropriate, as the slots will be invoked within the WebQueryThread and WebQueryResultThread.

        Asking a question about code? http://eel.is/iso-c++/testcase/

        S 1 Reply Last reply Reply Quote 0
        • S
          sheepdog @jeremy_k last edited by

          @jeremy_k Thank you very much for the advice. The clues provided did allow me to track down this:

          So I added Qt::DirectConnection and this now is caught when the button is pressed.
          

          Please don't do that! That causes your your slot to run in the GUI thread instead of your Algorithm's thread.

          The answer appears to be in that thread.

          1 Reply Last reply Reply Quote 0
          • First post
            Last post