Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. Qt for Python
  4. Occasionally get "QThread: Destroyed while thread is still running" when running multiple threads
Forum Updated to NodeBB v4.3 + New Features

Occasionally get "QThread: Destroyed while thread is still running" when running multiple threads

Scheduled Pinned Locked Moved Solved Qt for Python
qt for python
25 Posts 4 Posters 6.2k Views 1 Watching
  • 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.
  • G Offline
    G Offline
    gunraidan
    wrote on 16 Nov 2022, 07:04 last edited by
    #1

    So I'm trying to make a Pokedex that doesn't freeze when pulling data from the website's API.

    Full code of main window and main function.
    Abilities.py that has the load abilities thread.
    The Pokemon Dictionary in Pokecache is just a blank dictionary.

    This a work in progress so obviously the GUI isn't going to look beautiful, but you should get the gist of it.

    This is an example of me running the program. It seems to work fine but after hitting it multiple times it will crash:

    alt text

    As you can see the program ran fine but crashed. The log looks as such:

    Ability Thread: Alive
    Update Check Thread: Alive
    None
    Update Check Thread: Dead
    Abilities Thread: Dead
    Ability Thread: Alive
    Update Check Thread: Alive
    ['Has a 33% chance of curing any major status ailment after each turn.']
    Update Check Thread: Dead
    Abilities Thread: Dead
    Ability Thread: Alive
    Update Check Thread: Alive
    ["Increases moves' accuracy to 1.3×.", 'Doubles damage inflicted with not-very-effective moves.']     
    Update Check Thread: Dead
    QThread: Destroyed while thread is still running
    

    It crashes. I assume the "thread that is still running" was the ability thread as it didn't print that it was "dead".

    To go into specifics of how the program works.

    When starting the GUI the user is presented with a window where they can enter a name or number and press a button to retrieve information. When pressing the button the button clicked has the following code run:

    #The "Mother Code" Run        
        def extract(self):
            self.pokemon = self.line.text().lower()
            Data.run_api(self,"pokemon", self.pokemon)
            pokecache.pokemon_dict.update(self.data)
            self.name = pokecache.pokemon_dict["name"].title()
            abilities.load_abilities(self)
            Data.check_if_load(self)
    

    After running the api it starts running the abilities thread first:

    #Thread
    def load_abilities(self):
        global short_effects_updated
        short_effects_updated = False
        self.thread = QThread()
        self.worker = Worker()
        self.worker.moveToThread(self.thread)
        self.thread.started.connect(self.worker.abilities_data)
        
        
        self.worker.finished.connect(self.thread.quit)
        self.worker.finished.connect(self.worker.deleteLater)
        self.thread.started.connect(self.thread.deleteLater)
    
        self.worker.ab_data_pull.connect(ability_process)
        self.thread.start()
        
        self.thread.finished.connect(lambda:print("Abilities Thread: Dead"))
    

    This code pulls all of the abilities information from the API. (To see the full code of this segment click here)

    After that it runs the "check_if_load" thread which is as such:

    #Thread
        def check_if_load(self):
            self.update_thread = QThread()
            self.update_worker = Worker()
            self.update_worker.moveToThread(self.update_thread)
            self.update_thread.started.connect(self.update_worker.all_data)
            
            self.update_worker.finished.connect(self.update_thread.quit)
            self.update_worker.finished.connect(self.update_worker.deleteLater)
            self.update_thread.started.connect(self.update_thread.deleteLater)
            
            self.update_worker.data_pull.connect(Data.update_check)
            self.update_thread.start()
            
            #Resets
            self.update_thread.finished.connect(lambda:self.skin_label.setPixmap(QPixmap(f"{start}{directory}pokedexbgnew2.png")))
            self.update_thread.finished.connect(lambda:self.borders_screen.setPixmap(QPixmap(f"{start}{directory}foreground.png")))
            self.update_thread.finished.connect(lambda:self.button_s.setEnabled(True))
            self.update_thread.finished.connect(lambda:print("Update Check Thread: Dead"))
    

    The main part of this code is that it is connected to run "update_check" which is suppose to make specific changes after all the code is finished.

    It's coded as such:

        def update_check(self):
            while not abilities.short_effects_updated:
                None
            abilities.short_effects_updated = print(abilities.short_effects)
    

    Once the global flag in abilities no longer equals "None" it signals for update_check to run which prints the abilities.

    Again this all works fine but it eventually crashes with the error: "QThread: Destroyed while thread is still running".

    I'm wondering what I'm doing wrong and how I can fix it. Any help at all would be great! :)

    1 Reply Last reply
    0
    • G gunraidan
      20 Nov 2022, 20:27

      @JonB said in Occasionally get "QThread: Destroyed while thread is still running" when running multiple threads:

      @gunraidan said in Occasionally get "QThread: Destroyed while thread is still running" when running multiple threads:

      Doing the first results in this error:

      <PyQt6.QtCore.QJsonValue object at 0x00000182BF9CA570>

      I don't see it being an error. ("qt.tlsbackend.ossl: Failed to load libssl/libcrypto." is over to you, you have had that from the start.) So that actually looks good I think, it has found a QJsonValue in pokemon_dict["abilities"], so it's working.

      TypeError: the JSON object must be str, bytes or bytearray, not QByteArray

      Then you need to convert Qt QByteArray to bytes/bytearray, however you do that from PyQt6.

      When I type the following code:

          def handle_request(self, reply):
              er = reply.error()
              
              if er == QtNetwork.QNetworkReply.NetworkError.NoError:
                  bytes_string = reply.readAll()
                  pokemon_dict = QtCore.QJsonDocument.fromJson(bytes_string)
                  pokemon_dict = pokemon_dict.object()
                  print(pokemon_dict)
      

      This is the output:

      {'abilities': <PyQt6.QtCore.QJsonValue object at 0x000001EC6DE0A570>, 'base_experience': <PyQt6.QtCore.QJsonValue object at 0x000001EC6DE0A5E0>, 'forms': <PyQt6.QtCore.QJsonValue object at 0x000001EC6DE0A650>, 'game_indices': <PyQt6.QtCore.QJsonValue object at 0x000001EC6DE0A6C0>, 'height': <PyQt6.QtCore.QJsonValue object at 0x000001EC6DE0A730>, 'held_items': <PyQt6.QtCore.QJsonValue object at 0x000001EC6DE0A7A0>, 'id': <PyQt6.QtCore.QJsonValue object at 0x000001EC6DE0A810>, 'is_default': <PyQt6.QtCore.QJsonValue object at 0x000001EC6DE0A880>, 'location_area_encounters': <PyQt6.QtCore.QJsonValue object at 0x000001EC6DE0A8F0>, 'moves': <PyQt6.QtCore.QJsonValue object at 0x000001EC6DE0A960>, 'name': <PyQt6.QtCore.QJsonValue object at 0x000001EC6DE0A9D0>, 'order': <PyQt6.QtCore.QJsonValue object at 0x000001EC6DE0AA40>, 'past_types': <PyQt6.QtCore.QJsonValue object at 0x000001EC6DE0AAB0>, 'species': <PyQt6.QtCore.QJsonValue object at 0x000001EC6DE0AB20>, 'sprites': <PyQt6.QtCore.QJsonValue object at 0x000001EC6DE0AB90>, 'stats': <PyQt6.QtCore.QJsonValue object at 0x000001EC6DE0AC00>, 'types': <PyQt6.QtCore.QJsonValue object at 0x000001EC6DE0AC70>, 'weight': <PyQt6.QtCore.QJsonValue object at 0x000001EC6DE0ACE0>}
      

      So it does successfully import the data. However, unlike the keys, the values in the dictionary aren't strings but more so strange code. Is there a way to have the values be the same text string found in the api like the keys?

      J Online
      J Online
      JonB
      wrote on 21 Nov 2022, 10:18 last edited by JonB
      #19

      @gunraidan
      Here is the code (tested PyQt5) for the two possible approaches:

      import json
      
      from PyQt5 import QtCore
      
      if __name__ == '__main__':
          # I put your sample JSON into a file, since they are not arriving at my serial port
          f = QtCore.QFile("file.json")
          if not f.open(QtCore.QIODevice.ReadOnly):
              raise "Whoops"
          # following line's `readAll()` returns `QByteArray` type, just like when you read from serial port
          qbytearray = f.readAll()
          f.close()
      
          # Use `json.loads()` approach:
          # next line converts Qt `QByteArray` type to Python `bytes` type...
          pythonbytearray = bytes(qbytearray)
          # ...so that now it is acceptable to `json.loads(...)`
          pokemon_dict = json.loads(pythonbytearray)
          x = pokemon_dict["abilities"][0]['ability']['name']
          # next line prints `static`, which must be the value there
          print(x)
      
          # Use `QtCore.QJson...` approach:
          pokemon_dict = QtCore.QJsonDocument.fromJson(qbytearray)
          x = pokemon_dict["abilities"][0]['ability']['name'].toString()
          # next line prints `static`, which must be the value there
          print(x)
      
      

      As you can see, all you had to discover for Python/PyQt json.loads(...) is that you can convert a Qt QByteArray to a Python bytes array via bytes(qByteArrayValue).

      Use either one of these approaches. The json modules is slightly better integrated into Python than the Qt QJson... classes (e.g. note the QJson expression requires the toString() at the end, but the json one does not), so you may prefer to use the former. On the other hand, while json.loads() requires converting a QByteArray to a bytes, QJsonDocument.fromJson() does not.

      G 1 Reply Last reply 21 Nov 2022, 21:45
      2
      • SGaistS Offline
        SGaistS Offline
        SGaist
        Lifetime Qt Champion
        wrote on 16 Nov 2022, 21:12 last edited by
        #2

        Hi,

        Aren't that many threads a bit overkill ?
        Qt has QNetworkAccessManager to do API calls and it's asynchronous so it may fit the bill nicely without all the threads you seem to need.

        Interested in AI ? www.idiap.ch
        Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

        G 1 Reply Last reply 17 Nov 2022, 00:59
        0
        • SGaistS SGaist
          16 Nov 2022, 21:12

          Hi,

          Aren't that many threads a bit overkill ?
          Qt has QNetworkAccessManager to do API calls and it's asynchronous so it may fit the bill nicely without all the threads you seem to need.

          G Offline
          G Offline
          gunraidan
          wrote on 17 Nov 2022, 00:59 last edited by
          #3

          @SGaist said in Occasionally get "QThread: Destroyed while thread is still running" when running multiple threads:

          Hi,

          Aren't that many threads a bit overkill ?
          Qt has QNetworkAccessManager to do API calls and it's asynchronous so it may fit the bill nicely without all the threads you seem to need.

          I'm not family with it. Is there a good tutorial for it that uses Python?

          1 Reply Last reply
          0
          • SGaistS Offline
            SGaistS Offline
            SGaist
            Lifetime Qt Champion
            wrote on 17 Nov 2022, 21:02 last edited by
            #4

            There are basic examples on the Python documentation of the class.

            Interested in AI ? www.idiap.ch
            Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

            G 1 Reply Last reply 19 Nov 2022, 04:29
            0
            • SGaistS SGaist
              17 Nov 2022, 21:02

              There are basic examples on the Python documentation of the class.

              G Offline
              G Offline
              gunraidan
              wrote on 19 Nov 2022, 04:29 last edited by gunraidan
              #5

              @SGaist said in Occasionally get "QThread: Destroyed while thread is still running" when running multiple threads:

              There are basic examples on the Python documentation of the class.

              I managed to find more of a tutorial I had in mind.

              I got the code to work on my end, but now I'm trying to get it to work in a PyQt GUI.

              I can get the code to work in a GUI setting with the following:

              from PyQt6 import QtNetwork
              from PyQt6.QtCore import QUrl
              import sys
              
              from PyQt6.QtGui import*
              from PyQt6 import QtWidgets
              from PyQt6.QtWidgets import*
              
              class MainWindow(QWidget):  
                  def __init__ (self):
                      super().__init__()
                      self.title = "Window"
                      self.left = 200
                      self.top = 300
                      self.width = 300
                      self.height = 300
                      self.setWindowTitle(self.title)
                      self.setGeometry(self.left, self.top,self.width, self.height)
                      self.site_request()
                      self.start_button()
                      self.show()
                      
                  def start_button(self):
                      self.s_button = QtWidgets.QPushButton(self)
                      self.s_button.setText('Start')
                      self.s_button.clicked.connect(self.site_request)
                      
                  
                  def site_request(self):
                      url = 'http://webcode.me'
                      req = QtNetwork.QNetworkRequest(QUrl(url))
                      
                      self.nam = QtNetwork.QNetworkAccessManager()
                      self.nam.finished.connect(self.handle_request)
                      self.nam.get(req)
                      
                  def handle_request(self, reply):
                      er = reply.error()
                      
                      if er == QtNetwork.QNetworkReply.NetworkError.NoError:
                          
                          bytes_string = reply.readAll()
                          print(str(bytes_string, 'utf-8'))
                      else:
                          print ("Error")
                          print(reply.errorString())
                      
              
                      
              if __name__ == '__main__':        
                  app = QApplication(sys.argv) 
                  ex = MainWindow()        
                  code = app.exec()
                  sys.exit(code)
              

              I decided to make the the QNetworkAccessManager into the following:

                  def start_button(self):
                      self.s_button = QtWidgets.QPushButton(self)
                      self.s_button.setText('Start')
                      self.s_button.clicked.connect(GetData.site_request(self))
                      
              
              class GetData():
                  def __init__(self):
                      self.site_request()
                  
                  def site_request(self):
              
                      url = 'http://webcode.me'
                      req = QtNetwork.QNetworkRequest(QUrl(url))
                      
                      self.nam = QtNetwork.QNetworkAccessManager()
                      self.nam.finished.connect(GetData.handle_request(self,url))
                      self.nam.get(req)
                      
                  def handle_request(self, reply):
                      er = reply.error()
                      
                      if er == QtNetwork.QNetworkReply.NetworkError.NoError:
                          
                          bytes_string = reply.readAll()
                          print(str(bytes_string, 'utf-8'))
                      else:
                          print ("Error")
                          print(reply.errorString())
              

              When I run the code I get the following Traceback:

              Traceback (most recent call last):
                File "c:\Users\Nader\OneDrive\Documents\Coding\Python\TestNetwork.py", line 37, in site_request
                  self.nam = QtNetwork.QNetworkAccessManager()
              AttributeError: 'bool' object has no attribute 'nam'
              PS C:\Users\Nader\OneDrive\Documents\Coding\Python>  c:; cd 'c:\Users\Nader\OneDrive\Documents\Coding\Python'; & 'C:\Users\Nader\AppData\Local\Programs\Python\Python310\python.exe' 'c:\Users\Nader\.vscode\extensions\ms-python.python-2022.18.2\pythonFiles\lib\python\debugpy\adapter/../..\debugpy\launcher' '56993' '--' 'c:\Users\Nader\OneDrive\Documents\Coding\Python\TestNetwork.py' 
              Traceback (most recent call last):
                File "c:\Users\Nader\OneDrive\Documents\Coding\Python\TestNetwork.py", line 56, in <module>
                  ex = MainWindow()
                File "c:\Users\Nader\OneDrive\Documents\Coding\Python\TestNetwork.py", line 19, in __init__
                  self.start_button()
                File "c:\Users\Nader\OneDrive\Documents\Coding\Python\TestNetwork.py", line 25, in start_button
                  self.s_button.clicked.connect(GetData.site_request(self))
                File "c:\Users\Nader\OneDrive\Documents\Coding\Python\TestNetwork.py", line 38, in site_request
                  self.nam.finished.connect(GetData.handle_request(self,url))
                File "c:\Users\Nader\OneDrive\Documents\Coding\Python\TestNetwork.py", line 42, in handle_request
                  er = reply.error()
              AttributeError: 'str' object has no attribute 'error'
              

              I'm wondering what I'm doing wrong and how I can get the code functioning?

              Also when I pull data from this api, while I get the data it starts off with this:
              qt.tlsbackend.ossl: Failed to load libssl/libcrypto.

              J 1 Reply Last reply 19 Nov 2022, 11:18
              0
              • G gunraidan
                19 Nov 2022, 04:29

                @SGaist said in Occasionally get "QThread: Destroyed while thread is still running" when running multiple threads:

                There are basic examples on the Python documentation of the class.

                I managed to find more of a tutorial I had in mind.

                I got the code to work on my end, but now I'm trying to get it to work in a PyQt GUI.

                I can get the code to work in a GUI setting with the following:

                from PyQt6 import QtNetwork
                from PyQt6.QtCore import QUrl
                import sys
                
                from PyQt6.QtGui import*
                from PyQt6 import QtWidgets
                from PyQt6.QtWidgets import*
                
                class MainWindow(QWidget):  
                    def __init__ (self):
                        super().__init__()
                        self.title = "Window"
                        self.left = 200
                        self.top = 300
                        self.width = 300
                        self.height = 300
                        self.setWindowTitle(self.title)
                        self.setGeometry(self.left, self.top,self.width, self.height)
                        self.site_request()
                        self.start_button()
                        self.show()
                        
                    def start_button(self):
                        self.s_button = QtWidgets.QPushButton(self)
                        self.s_button.setText('Start')
                        self.s_button.clicked.connect(self.site_request)
                        
                    
                    def site_request(self):
                        url = 'http://webcode.me'
                        req = QtNetwork.QNetworkRequest(QUrl(url))
                        
                        self.nam = QtNetwork.QNetworkAccessManager()
                        self.nam.finished.connect(self.handle_request)
                        self.nam.get(req)
                        
                    def handle_request(self, reply):
                        er = reply.error()
                        
                        if er == QtNetwork.QNetworkReply.NetworkError.NoError:
                            
                            bytes_string = reply.readAll()
                            print(str(bytes_string, 'utf-8'))
                        else:
                            print ("Error")
                            print(reply.errorString())
                        
                
                        
                if __name__ == '__main__':        
                    app = QApplication(sys.argv) 
                    ex = MainWindow()        
                    code = app.exec()
                    sys.exit(code)
                

                I decided to make the the QNetworkAccessManager into the following:

                    def start_button(self):
                        self.s_button = QtWidgets.QPushButton(self)
                        self.s_button.setText('Start')
                        self.s_button.clicked.connect(GetData.site_request(self))
                        
                
                class GetData():
                    def __init__(self):
                        self.site_request()
                    
                    def site_request(self):
                
                        url = 'http://webcode.me'
                        req = QtNetwork.QNetworkRequest(QUrl(url))
                        
                        self.nam = QtNetwork.QNetworkAccessManager()
                        self.nam.finished.connect(GetData.handle_request(self,url))
                        self.nam.get(req)
                        
                    def handle_request(self, reply):
                        er = reply.error()
                        
                        if er == QtNetwork.QNetworkReply.NetworkError.NoError:
                            
                            bytes_string = reply.readAll()
                            print(str(bytes_string, 'utf-8'))
                        else:
                            print ("Error")
                            print(reply.errorString())
                

                When I run the code I get the following Traceback:

                Traceback (most recent call last):
                  File "c:\Users\Nader\OneDrive\Documents\Coding\Python\TestNetwork.py", line 37, in site_request
                    self.nam = QtNetwork.QNetworkAccessManager()
                AttributeError: 'bool' object has no attribute 'nam'
                PS C:\Users\Nader\OneDrive\Documents\Coding\Python>  c:; cd 'c:\Users\Nader\OneDrive\Documents\Coding\Python'; & 'C:\Users\Nader\AppData\Local\Programs\Python\Python310\python.exe' 'c:\Users\Nader\.vscode\extensions\ms-python.python-2022.18.2\pythonFiles\lib\python\debugpy\adapter/../..\debugpy\launcher' '56993' '--' 'c:\Users\Nader\OneDrive\Documents\Coding\Python\TestNetwork.py' 
                Traceback (most recent call last):
                  File "c:\Users\Nader\OneDrive\Documents\Coding\Python\TestNetwork.py", line 56, in <module>
                    ex = MainWindow()
                  File "c:\Users\Nader\OneDrive\Documents\Coding\Python\TestNetwork.py", line 19, in __init__
                    self.start_button()
                  File "c:\Users\Nader\OneDrive\Documents\Coding\Python\TestNetwork.py", line 25, in start_button
                    self.s_button.clicked.connect(GetData.site_request(self))
                  File "c:\Users\Nader\OneDrive\Documents\Coding\Python\TestNetwork.py", line 38, in site_request
                    self.nam.finished.connect(GetData.handle_request(self,url))
                  File "c:\Users\Nader\OneDrive\Documents\Coding\Python\TestNetwork.py", line 42, in handle_request
                    er = reply.error()
                AttributeError: 'str' object has no attribute 'error'
                

                I'm wondering what I'm doing wrong and how I can get the code functioning?

                Also when I pull data from this api, while I get the data it starts off with this:
                qt.tlsbackend.ossl: Failed to load libssl/libcrypto.

                J Online
                J Online
                JonB
                wrote on 19 Nov 2022, 11:18 last edited by JonB
                #6

                @gunraidan said in Occasionally get "QThread: Destroyed while thread is still running" when running multiple threads:

                self.nam = QtNetwork.QNetworkAccessManager()
                AttributeError: 'bool' object has no attribute 'nam'
                
                er = reply.error()
                AttributeError: 'str' object has no attribute 'error'
                

                These are both very strange errors to receive, hard to know what is going on from your code to cause.

                I decided to make the the QNetworkAccessManager into the following:

                I don't understand what this means, in what sense "make the QNetworkAccessManager" into anything?

                self.nam.finished.connect(GetData.handle_request(self,url))
                

                What is going on here? Where did you get an example of using such a construct for connect? If you just "invented" this yourself, it's wrong :) I would expect this to completely go wrong, goodness knows what the finished signal actually gets connected to after executing this line? At minimum I can see how/why this line would cause the

                er = reply.error()
                AttributeError: 'str' object has no attribute 'error'
                

                Which is why the original self.nam.finished.connect(self.handle_request) works correctly but your change does not. Similarly with your change over to GetData.site_request(self). You have changed currently working code to something different for no apparent reason and then wonder why it does not work! :)

                G 1 Reply Last reply 19 Nov 2022, 18:35
                1
                • J JonB
                  19 Nov 2022, 11:18

                  @gunraidan said in Occasionally get "QThread: Destroyed while thread is still running" when running multiple threads:

                  self.nam = QtNetwork.QNetworkAccessManager()
                  AttributeError: 'bool' object has no attribute 'nam'
                  
                  er = reply.error()
                  AttributeError: 'str' object has no attribute 'error'
                  

                  These are both very strange errors to receive, hard to know what is going on from your code to cause.

                  I decided to make the the QNetworkAccessManager into the following:

                  I don't understand what this means, in what sense "make the QNetworkAccessManager" into anything?

                  self.nam.finished.connect(GetData.handle_request(self,url))
                  

                  What is going on here? Where did you get an example of using such a construct for connect? If you just "invented" this yourself, it's wrong :) I would expect this to completely go wrong, goodness knows what the finished signal actually gets connected to after executing this line? At minimum I can see how/why this line would cause the

                  er = reply.error()
                  AttributeError: 'str' object has no attribute 'error'
                  

                  Which is why the original self.nam.finished.connect(self.handle_request) works correctly but your change does not. Similarly with your change over to GetData.site_request(self). You have changed currently working code to something different for no apparent reason and then wonder why it does not work! :)

                  G Offline
                  G Offline
                  gunraidan
                  wrote on 19 Nov 2022, 18:35 last edited by
                  #7

                  @JonB said in Occasionally get "QThread: Destroyed while thread is still running" when running multiple threads:

                  @gunraidan said in Occasionally get "QThread: Destroyed while thread is still running" when running multiple threads:

                  self.nam = QtNetwork.QNetworkAccessManager()
                  AttributeError: 'bool' object has no attribute 'nam'
                  
                  er = reply.error()
                  AttributeError: 'str' object has no attribute 'error'
                  

                  These are both very strange errors to receive, hard to know what is going on from your code to cause.

                  I decided to make the the QNetworkAccessManager into the following:

                  I don't understand what this means, in what sense "make the QNetworkAccessManager" into anything?

                  self.nam.finished.connect(GetData.handle_request(self,url))
                  

                  What is going on here? Where did you get an example of using such a construct for connect? If you just "invented" this yourself, it's wrong :) I would expect this to completely go wrong, goodness knows what the finished signal actually gets connected to after executing this line? At minimum I can see how/why this line would cause the

                  er = reply.error()
                  AttributeError: 'str' object has no attribute 'error'
                  

                  Which is why the original self.nam.finished.connect(self.handle_request) works correctly but your change does not. Similarly with your change over to GetData.site_request(self). You have changed currently working code to something different for no apparent reason and then wonder why it does not work! :)

                  The reason why I changed it is because when I simply put the code in a new class as such:

                      def start_button(self):
                          self.s_button = QtWidgets.QPushButton(self)
                          self.s_button.setText('Start')
                          self.s_button.clicked.connect(self.site_request)
                          
                  
                  class GetData():
                      def __init__(self):
                          self.site_request()
                      
                      def site_request(self):
                  
                          url = 'http://webcode.me'
                          req = QtNetwork.QNetworkRequest(QUrl(url))
                          
                          self.nam = QtNetwork.QNetworkAccessManager()
                          self.nam.finished.connect(self.handle_request)
                          self.nam.get(req)
                          
                      def handle_request(self, reply):
                          er = reply.error()
                          
                          if er == QtNetwork.QNetworkReply.NetworkError.NoError:
                              
                              bytes_string = reply.readAll()
                              print(str(bytes_string, 'utf-8'))
                          else:
                              print ("Error")
                              print(reply.errorString())
                  

                  I get the following Traceback:

                  Traceback (most recent call last):
                    File "c:\Users\Nader\OneDrive\Documents\Coding\Python\TestNetworkClass.py", line 59, in <module>
                      ex = MainWindow()        
                    File "c:\Users\Nader\OneDrive\Documents\Coding\Python\TestNetworkClass.py", line 22, in __init__
                      self.start_button()
                    File "c:\Users\Nader\OneDrive\Documents\Coding\Python\TestNetworkClass.py", line 28, in start_button
                      self.s_button.clicked.connect(self.site_request)
                  AttributeError: 'MainWindow' object has no attribute 'site_request'
                  

                  When changing the button connect to the following:

                      def start_button(self):
                          self.s_button = QtWidgets.QPushButton(self)
                          self.s_button.setText('Start')
                          self.s_button.clicked.connect(GetData.site_request)
                  

                  Doing so starts the GUI but upon hitting the start button I get this Traceback:

                  Traceback (most recent call last):
                    File "c:\Users\Nader\OneDrive\Documents\Coding\Python\TestNetworkClass.py", line 40, in site_request
                      self.nam = QtNetwork.QNetworkAccessManager()
                  AttributeError: 'bool' object has no attribute 'nam'
                  

                  Changing the button connect to GetData.site_request(self) results in this Traceback:

                  Traceback (most recent call last):
                    File "c:\Users\Nader\OneDrive\Documents\Coding\Python\TestNetworkClass.py", line 59, in <module>
                      ex = MainWindow()
                    File "c:\Users\Nader\OneDrive\Documents\Coding\Python\TestNetworkClass.py", line 22, in __init__
                      self.start_button()
                    File "c:\Users\Nader\OneDrive\Documents\Coding\Python\TestNetworkClass.py", line 28, in start_button
                      self.s_button.clicked.connect(GetData.site_request(self))
                    File "c:\Users\Nader\OneDrive\Documents\Coding\Python\TestNetworkClass.py", line 41, in site_request
                      self.nam.finished.connect(self.handle_request)
                  AttributeError: 'MainWindow' object has no attribute 'handle_request'
                  

                  So I decided to change self.nam.finished.connect(self.handle_request) to self.nam.finished.connect(GetData.handle_request(self)).

                  Running that I got the following error:

                    File "c:\Users\Nader\OneDrive\Documents\Coding\Python\TestNetworkClass.py", line 41, in site_request
                      self.nam.finished.connect(GetData.handle_request(self))
                  TypeError: GetData.handle_request() missing 1 required positional argument: 'reply'
                  

                  So I figured the reply variable needed the url to process as that's how it traditionally works when getting api in Python.

                  J 1 Reply Last reply 19 Nov 2022, 18:47
                  0
                  • G gunraidan
                    19 Nov 2022, 18:35

                    @JonB said in Occasionally get "QThread: Destroyed while thread is still running" when running multiple threads:

                    @gunraidan said in Occasionally get "QThread: Destroyed while thread is still running" when running multiple threads:

                    self.nam = QtNetwork.QNetworkAccessManager()
                    AttributeError: 'bool' object has no attribute 'nam'
                    
                    er = reply.error()
                    AttributeError: 'str' object has no attribute 'error'
                    

                    These are both very strange errors to receive, hard to know what is going on from your code to cause.

                    I decided to make the the QNetworkAccessManager into the following:

                    I don't understand what this means, in what sense "make the QNetworkAccessManager" into anything?

                    self.nam.finished.connect(GetData.handle_request(self,url))
                    

                    What is going on here? Where did you get an example of using such a construct for connect? If you just "invented" this yourself, it's wrong :) I would expect this to completely go wrong, goodness knows what the finished signal actually gets connected to after executing this line? At minimum I can see how/why this line would cause the

                    er = reply.error()
                    AttributeError: 'str' object has no attribute 'error'
                    

                    Which is why the original self.nam.finished.connect(self.handle_request) works correctly but your change does not. Similarly with your change over to GetData.site_request(self). You have changed currently working code to something different for no apparent reason and then wonder why it does not work! :)

                    The reason why I changed it is because when I simply put the code in a new class as such:

                        def start_button(self):
                            self.s_button = QtWidgets.QPushButton(self)
                            self.s_button.setText('Start')
                            self.s_button.clicked.connect(self.site_request)
                            
                    
                    class GetData():
                        def __init__(self):
                            self.site_request()
                        
                        def site_request(self):
                    
                            url = 'http://webcode.me'
                            req = QtNetwork.QNetworkRequest(QUrl(url))
                            
                            self.nam = QtNetwork.QNetworkAccessManager()
                            self.nam.finished.connect(self.handle_request)
                            self.nam.get(req)
                            
                        def handle_request(self, reply):
                            er = reply.error()
                            
                            if er == QtNetwork.QNetworkReply.NetworkError.NoError:
                                
                                bytes_string = reply.readAll()
                                print(str(bytes_string, 'utf-8'))
                            else:
                                print ("Error")
                                print(reply.errorString())
                    

                    I get the following Traceback:

                    Traceback (most recent call last):
                      File "c:\Users\Nader\OneDrive\Documents\Coding\Python\TestNetworkClass.py", line 59, in <module>
                        ex = MainWindow()        
                      File "c:\Users\Nader\OneDrive\Documents\Coding\Python\TestNetworkClass.py", line 22, in __init__
                        self.start_button()
                      File "c:\Users\Nader\OneDrive\Documents\Coding\Python\TestNetworkClass.py", line 28, in start_button
                        self.s_button.clicked.connect(self.site_request)
                    AttributeError: 'MainWindow' object has no attribute 'site_request'
                    

                    When changing the button connect to the following:

                        def start_button(self):
                            self.s_button = QtWidgets.QPushButton(self)
                            self.s_button.setText('Start')
                            self.s_button.clicked.connect(GetData.site_request)
                    

                    Doing so starts the GUI but upon hitting the start button I get this Traceback:

                    Traceback (most recent call last):
                      File "c:\Users\Nader\OneDrive\Documents\Coding\Python\TestNetworkClass.py", line 40, in site_request
                        self.nam = QtNetwork.QNetworkAccessManager()
                    AttributeError: 'bool' object has no attribute 'nam'
                    

                    Changing the button connect to GetData.site_request(self) results in this Traceback:

                    Traceback (most recent call last):
                      File "c:\Users\Nader\OneDrive\Documents\Coding\Python\TestNetworkClass.py", line 59, in <module>
                        ex = MainWindow()
                      File "c:\Users\Nader\OneDrive\Documents\Coding\Python\TestNetworkClass.py", line 22, in __init__
                        self.start_button()
                      File "c:\Users\Nader\OneDrive\Documents\Coding\Python\TestNetworkClass.py", line 28, in start_button
                        self.s_button.clicked.connect(GetData.site_request(self))
                      File "c:\Users\Nader\OneDrive\Documents\Coding\Python\TestNetworkClass.py", line 41, in site_request
                        self.nam.finished.connect(self.handle_request)
                    AttributeError: 'MainWindow' object has no attribute 'handle_request'
                    

                    So I decided to change self.nam.finished.connect(self.handle_request) to self.nam.finished.connect(GetData.handle_request(self)).

                    Running that I got the following error:

                      File "c:\Users\Nader\OneDrive\Documents\Coding\Python\TestNetworkClass.py", line 41, in site_request
                        self.nam.finished.connect(GetData.handle_request(self))
                    TypeError: GetData.handle_request() missing 1 required positional argument: 'reply'
                    

                    So I figured the reply variable needed the url to process as that's how it traditionally works when getting api in Python.

                    J Online
                    J Online
                    JonB
                    wrote on 19 Nov 2022, 18:47 last edited by
                    #8

                    @gunraidan
                    Your attempts to introduce the GetData class, and the way you try to use GetData, are wrong. They might make some sense of you created a GetData instance. I don't know what you trying to achieve.

                    G 1 Reply Last reply 19 Nov 2022, 22:22
                    1
                    • J JonB
                      19 Nov 2022, 18:47

                      @gunraidan
                      Your attempts to introduce the GetData class, and the way you try to use GetData, are wrong. They might make some sense of you created a GetData instance. I don't know what you trying to achieve.

                      G Offline
                      G Offline
                      gunraidan
                      wrote on 19 Nov 2022, 22:22 last edited by
                      #9

                      @JonB said in Occasionally get "QThread: Destroyed while thread is still running" when running multiple threads:

                      @gunraidan
                      Your attempts to introduce the GetData class, and the way you try to use GetData, are wrong. They might make some sense of you created a GetData instance. I don't know what you trying to achieve.

                      I'll just forget about it then.

                      I realize that I've been asking a lot in this thread, so I understand if I get ignored, but I do have a new issue that is very important and I can't figure out.

                      I want to pull information from this api page.

                      Traditional what I would do would create an api request get function:

                          def run_api(self):
                              contact = {'User-Agent': '("Accept: application/json", "Cache-Control: max-age=360",)'}
                              response = requests.get ('https://pokeapi.co/api/v2/pokemon/pikachu'}', headers = contact)
                              self.data = response.json()
                      

                      I would then create a dictionary:
                      pokemon_dict = []

                      And then in the main function have the api get request save the information to the dictionary:

                      pokemon_dict.update(self.data)
                      

                      Then I would print out something specific from the dictionary.
                      Such as pokemon_dict["abilities"] which would print all the information in abilities. Or something even more specific like pokemon_dict["abilities"][0]['ability']['name'] which would print the name of the first ability under abilities, which in this case the output of the code would print static.

                      When I try the same with the code when using QNetwork it doesn't really work.

                      For example take the code below:

                      from PyQt6 import QtNetwork
                      from PyQt6.QtCore import QUrl
                      import sys
                      
                      from PyQt6.QtGui import*
                      from PyQt6 import QtWidgets
                      from PyQt6.QtWidgets import*
                      
                      pokemon_dict = []
                      
                      class MainWindow(QWidget):  
                          def __init__ (self):
                              super().__init__()
                              self.title = "Window"
                              self.left = 200
                              self.top = 300
                              self.width = 300
                              self.height = 300
                              self.setWindowTitle(self.title)
                              self.setGeometry(self.left, self.top,self.width, self.height)
                      
                              self.start_button()
                              self.show()
                              
                          def start_button(self):
                              self.s_button = QtWidgets.QPushButton(self)
                              self.s_button.setText('Start')
                              self.s_button.clicked.connect(self.site_request)
                              
                          
                          def site_request(self):
                              url = 'https://pokeapi.co/api/v2/pokemon/pikachu'
                              req = QtNetwork.QNetworkRequest(QUrl(url))
                              
                              self.nam = QtNetwork.QNetworkAccessManager()
                              self.nam.finished.connect(self.handle_request)
                              self.nam.get(req)
                              
                          def handle_request(self, reply):
                              er = reply.error()
                              
                              if er == QtNetwork.QNetworkReply.NetworkError.NoError:
                                  
                                  bytes_string = reply.readAll()
                                  pokemon_dict = bytes_string
                                  pokemon_dict.append(bytes_string)
                                  print(pokemon_dict)
                              else:
                                  print ("Error")
                                  print(reply.errorString())
                              
                      
                              
                      if __name__ == '__main__':        
                          app = QApplication(sys.argv) 
                          ex = MainWindow()        
                          code = app.exec()
                          sys.exit(code)
                      

                      This successfully prints out everything in the api page as this is the output.

                      Interestingly, besides the qt.tlsbackend.ossl: Failed to load libssl/libcrypto. that people aren't sure what that is, it also starts the dictionary off with b', something that is not present in the original api link.

                      So doing something such as:

                          def handle_request(self, reply):
                              er = reply.error()
                              
                              if er == QtNetwork.QNetworkReply.NetworkError.NoError:
                                  
                                  bytes_string = reply.readAll()
                                  pokemon_dict = bytes_string
                                  pokemon_dict.append(bytes_string)
                                  print(pokemon_dict["abilities"])
                      

                      Results in this output:

                      qt.tlsbackend.ossl: Failed to load libssl/libcrypto.
                      Traceback (most recent call last):
                        File "c:\Users\Nader\OneDrive\Documents\Coding\Python\TestNetwork.py", line 47, in handle_request
                          print(pokemon_dict["abilities"])
                      TypeError: QByteArray.__getitem__(): arguments did not match any overloaded call:
                        overload 1: argument 1 has unexpected type 'str'
                        overload 2: argument 1 has unexpected type 'str'
                      

                      The same occurs when I do print(pokemon_dict["b"]) instead.

                      Entering print(pokemon_dict[0]) outputs b'{'. But changing the function to print(pokemon_dict["b'{'"]) results in the same previous Traceback.

                      I'm wondering what I am doing wrong? Any help at all would be greatly appreciated!

                      J 1 Reply Last reply 19 Nov 2022, 22:35
                      0
                      • G gunraidan
                        19 Nov 2022, 22:22

                        @JonB said in Occasionally get "QThread: Destroyed while thread is still running" when running multiple threads:

                        @gunraidan
                        Your attempts to introduce the GetData class, and the way you try to use GetData, are wrong. They might make some sense of you created a GetData instance. I don't know what you trying to achieve.

                        I'll just forget about it then.

                        I realize that I've been asking a lot in this thread, so I understand if I get ignored, but I do have a new issue that is very important and I can't figure out.

                        I want to pull information from this api page.

                        Traditional what I would do would create an api request get function:

                            def run_api(self):
                                contact = {'User-Agent': '("Accept: application/json", "Cache-Control: max-age=360",)'}
                                response = requests.get ('https://pokeapi.co/api/v2/pokemon/pikachu'}', headers = contact)
                                self.data = response.json()
                        

                        I would then create a dictionary:
                        pokemon_dict = []

                        And then in the main function have the api get request save the information to the dictionary:

                        pokemon_dict.update(self.data)
                        

                        Then I would print out something specific from the dictionary.
                        Such as pokemon_dict["abilities"] which would print all the information in abilities. Or something even more specific like pokemon_dict["abilities"][0]['ability']['name'] which would print the name of the first ability under abilities, which in this case the output of the code would print static.

                        When I try the same with the code when using QNetwork it doesn't really work.

                        For example take the code below:

                        from PyQt6 import QtNetwork
                        from PyQt6.QtCore import QUrl
                        import sys
                        
                        from PyQt6.QtGui import*
                        from PyQt6 import QtWidgets
                        from PyQt6.QtWidgets import*
                        
                        pokemon_dict = []
                        
                        class MainWindow(QWidget):  
                            def __init__ (self):
                                super().__init__()
                                self.title = "Window"
                                self.left = 200
                                self.top = 300
                                self.width = 300
                                self.height = 300
                                self.setWindowTitle(self.title)
                                self.setGeometry(self.left, self.top,self.width, self.height)
                        
                                self.start_button()
                                self.show()
                                
                            def start_button(self):
                                self.s_button = QtWidgets.QPushButton(self)
                                self.s_button.setText('Start')
                                self.s_button.clicked.connect(self.site_request)
                                
                            
                            def site_request(self):
                                url = 'https://pokeapi.co/api/v2/pokemon/pikachu'
                                req = QtNetwork.QNetworkRequest(QUrl(url))
                                
                                self.nam = QtNetwork.QNetworkAccessManager()
                                self.nam.finished.connect(self.handle_request)
                                self.nam.get(req)
                                
                            def handle_request(self, reply):
                                er = reply.error()
                                
                                if er == QtNetwork.QNetworkReply.NetworkError.NoError:
                                    
                                    bytes_string = reply.readAll()
                                    pokemon_dict = bytes_string
                                    pokemon_dict.append(bytes_string)
                                    print(pokemon_dict)
                                else:
                                    print ("Error")
                                    print(reply.errorString())
                                
                        
                                
                        if __name__ == '__main__':        
                            app = QApplication(sys.argv) 
                            ex = MainWindow()        
                            code = app.exec()
                            sys.exit(code)
                        

                        This successfully prints out everything in the api page as this is the output.

                        Interestingly, besides the qt.tlsbackend.ossl: Failed to load libssl/libcrypto. that people aren't sure what that is, it also starts the dictionary off with b', something that is not present in the original api link.

                        So doing something such as:

                            def handle_request(self, reply):
                                er = reply.error()
                                
                                if er == QtNetwork.QNetworkReply.NetworkError.NoError:
                                    
                                    bytes_string = reply.readAll()
                                    pokemon_dict = bytes_string
                                    pokemon_dict.append(bytes_string)
                                    print(pokemon_dict["abilities"])
                        

                        Results in this output:

                        qt.tlsbackend.ossl: Failed to load libssl/libcrypto.
                        Traceback (most recent call last):
                          File "c:\Users\Nader\OneDrive\Documents\Coding\Python\TestNetwork.py", line 47, in handle_request
                            print(pokemon_dict["abilities"])
                        TypeError: QByteArray.__getitem__(): arguments did not match any overloaded call:
                          overload 1: argument 1 has unexpected type 'str'
                          overload 2: argument 1 has unexpected type 'str'
                        

                        The same occurs when I do print(pokemon_dict["b"]) instead.

                        Entering print(pokemon_dict[0]) outputs b'{'. But changing the function to print(pokemon_dict["b'{'"]) results in the same previous Traceback.

                        I'm wondering what I am doing wrong? Any help at all would be greatly appreciated!

                        J Online
                        J Online
                        JonB
                        wrote on 19 Nov 2022, 22:35 last edited by JonB
                        #10

                        @gunraidan
                        I am guessing the reply is a JSON string? [https://pokeapi.co/api/v2/pokemon/25 : yes it is.] You need to parse it with a Python library or JSON Support in Qt.

                        pokemon_dict is an array of bytes (Python list), it's not a dictionary, you can't index that with a string hence the error message. Be aware that your code

                                    pokemon_dict = bytes_string
                                    pokemon_dict.append(bytes_string)
                        

                        is it making it be two copies of the input bytes_string.

                        G 1 Reply Last reply 20 Nov 2022, 01:40
                        0
                        • J JonB
                          19 Nov 2022, 22:35

                          @gunraidan
                          I am guessing the reply is a JSON string? [https://pokeapi.co/api/v2/pokemon/25 : yes it is.] You need to parse it with a Python library or JSON Support in Qt.

                          pokemon_dict is an array of bytes (Python list), it's not a dictionary, you can't index that with a string hence the error message. Be aware that your code

                                      pokemon_dict = bytes_string
                                      pokemon_dict.append(bytes_string)
                          

                          is it making it be two copies of the input bytes_string.

                          G Offline
                          G Offline
                          gunraidan
                          wrote on 20 Nov 2022, 01:40 last edited by
                          #11

                          @JonB

                          Thank you for your response.

                          pokemon_dict = bytes_string was left in by accident.

                          I just want to be able to navigate through the api, the same or a similar way as using the traditional Python api method.

                          I don't see a template in the link you've provided, and possibly I'm just bad at Googling, but I can't really find anything online. Do you know of any simple templates I can find online? Or, if you could please, show me a quick mock up excerpt if that wouldn't be too much trouble?

                          J 1 Reply Last reply 20 Nov 2022, 10:07
                          0
                          • G gunraidan
                            20 Nov 2022, 01:40

                            @JonB

                            Thank you for your response.

                            pokemon_dict = bytes_string was left in by accident.

                            I just want to be able to navigate through the api, the same or a similar way as using the traditional Python api method.

                            I don't see a template in the link you've provided, and possibly I'm just bad at Googling, but I can't really find anything online. Do you know of any simple templates I can find online? Or, if you could please, show me a quick mock up excerpt if that wouldn't be too much trouble?

                            J Online
                            J Online
                            JonB
                            wrote on 20 Nov 2022, 10:07 last edited by JonB
                            #12

                            @gunraidan
                            As I said, you are just missing one step. The bytes_string you get is just a string of the bytes/characters which arrive/come from file. You cannot access the "keys", like pokemon_dict["abilities"], until you have called some JSON library to parse that text as JSON, which is what it is.

                            For the JSON you have two choices: Qt has QJson... classes or Python has its own JSON library/classes. You might use either one.

                            For the Qt, untested but try:

                            from PyQt6 import QtCore
                            
                            bytes_string = reply.readAll()
                            pokemon_dict = QtCore.QJsonDocument.fromJson(bytes_string)
                            # you may need next line, not sure:
                            # pokemon_dict = pokemon_dict.object()
                            print(pokemon_dict["abilities"])
                            

                            Or you may prefer to do this with the Python JSON classes --- https://docs.python.org/3/library/json.html. I think that would be

                            import json
                            
                            bytes_string = reply.readAll()
                            pokemon_dict = json.loads(bytes_string)
                            print(pokemon_dict["abilities"])
                            
                            G 1 Reply Last reply 20 Nov 2022, 18:52
                            0
                            • J JonB
                              20 Nov 2022, 10:07

                              @gunraidan
                              As I said, you are just missing one step. The bytes_string you get is just a string of the bytes/characters which arrive/come from file. You cannot access the "keys", like pokemon_dict["abilities"], until you have called some JSON library to parse that text as JSON, which is what it is.

                              For the JSON you have two choices: Qt has QJson... classes or Python has its own JSON library/classes. You might use either one.

                              For the Qt, untested but try:

                              from PyQt6 import QtCore
                              
                              bytes_string = reply.readAll()
                              pokemon_dict = QtCore.QJsonDocument.fromJson(bytes_string)
                              # you may need next line, not sure:
                              # pokemon_dict = pokemon_dict.object()
                              print(pokemon_dict["abilities"])
                              

                              Or you may prefer to do this with the Python JSON classes --- https://docs.python.org/3/library/json.html. I think that would be

                              import json
                              
                              bytes_string = reply.readAll()
                              pokemon_dict = json.loads(bytes_string)
                              print(pokemon_dict["abilities"])
                              
                              G Offline
                              G Offline
                              gunraidan
                              wrote on 20 Nov 2022, 18:52 last edited by
                              #13

                              @JonB said in Occasionally get "QThread: Destroyed while thread is still running" when running multiple threads:

                              @gunraidan
                              As I said, you are just missing one step. The bytes_string you get is just a string of the bytes/characters which arrive/come from file. You cannot access the "keys", like pokemon_dict["abilities"], until you have called some JSON library to parse that text as JSON, which is what it is.

                              For the JSON you have two choices: Qt has QJson... classes or Python has its own JSON library/classes. You might use either one.

                              For the Qt, untested but try:

                              from PyQt6 import QtCore
                              
                              bytes_string = reply.readAll()
                              pokemon_dict = QtCore.QJsonDocument.fromJson(bytes_string)
                              # you may need next line, not sure:
                              # pokemon_dict = pokemon_dict.object()
                              print(pokemon_dict["abilities"])
                              

                              Or you may prefer to do this with the Python JSON classes --- https://docs.python.org/3/library/json.html. I think that would be

                              import json
                              
                              bytes_string = reply.readAll()
                              pokemon_dict = json.loads(bytes_string)
                              print(pokemon_dict["abilities"])
                              

                              Doing the first results in this error:

                              qt.tlsbackend.ossl: Failed to load libssl/libcrypto.
                              <PyQt6.QtCore.QJsonValue object at 0x00000182BF9CA570>
                              

                              Doing the second results in this error:

                              Traceback (most recent call last):
                                File "c:\Users\Nader\OneDrive\Documents\Coding\Python\TestNetwork.py", line 44, in handle_request
                                  pokemon_dict = json.loads(bytes_string)
                                File "C:\Users\Nader\AppData\Local\Programs\Python\Python310\lib\json\__init__.py", line 339, in loads
                                  raise TypeError(f'the JSON object must be str, bytes or bytearray, '
                              TypeError: the JSON object must be str, bytes or bytearray, not QByteArray
                              
                              J 1 Reply Last reply 20 Nov 2022, 18:57
                              0
                              • G gunraidan
                                20 Nov 2022, 18:52

                                @JonB said in Occasionally get "QThread: Destroyed while thread is still running" when running multiple threads:

                                @gunraidan
                                As I said, you are just missing one step. The bytes_string you get is just a string of the bytes/characters which arrive/come from file. You cannot access the "keys", like pokemon_dict["abilities"], until you have called some JSON library to parse that text as JSON, which is what it is.

                                For the JSON you have two choices: Qt has QJson... classes or Python has its own JSON library/classes. You might use either one.

                                For the Qt, untested but try:

                                from PyQt6 import QtCore
                                
                                bytes_string = reply.readAll()
                                pokemon_dict = QtCore.QJsonDocument.fromJson(bytes_string)
                                # you may need next line, not sure:
                                # pokemon_dict = pokemon_dict.object()
                                print(pokemon_dict["abilities"])
                                

                                Or you may prefer to do this with the Python JSON classes --- https://docs.python.org/3/library/json.html. I think that would be

                                import json
                                
                                bytes_string = reply.readAll()
                                pokemon_dict = json.loads(bytes_string)
                                print(pokemon_dict["abilities"])
                                

                                Doing the first results in this error:

                                qt.tlsbackend.ossl: Failed to load libssl/libcrypto.
                                <PyQt6.QtCore.QJsonValue object at 0x00000182BF9CA570>
                                

                                Doing the second results in this error:

                                Traceback (most recent call last):
                                  File "c:\Users\Nader\OneDrive\Documents\Coding\Python\TestNetwork.py", line 44, in handle_request
                                    pokemon_dict = json.loads(bytes_string)
                                  File "C:\Users\Nader\AppData\Local\Programs\Python\Python310\lib\json\__init__.py", line 339, in loads
                                    raise TypeError(f'the JSON object must be str, bytes or bytearray, '
                                TypeError: the JSON object must be str, bytes or bytearray, not QByteArray
                                
                                J Online
                                J Online
                                JonB
                                wrote on 20 Nov 2022, 18:57 last edited by JonB
                                #14

                                @gunraidan said in Occasionally get "QThread: Destroyed while thread is still running" when running multiple threads:

                                Doing the first results in this error:

                                <PyQt6.QtCore.QJsonValue object at 0x00000182BF9CA570>

                                I don't see it being an error. ("qt.tlsbackend.ossl: Failed to load libssl/libcrypto." is over to you, you have had that from the start.) So that actually looks good I think, it has found a QJsonValue in pokemon_dict["abilities"], so it's working.

                                TypeError: the JSON object must be str, bytes or bytearray, not QByteArray

                                Then you need to convert Qt QByteArray to bytes/bytearray, however you do that from PyQt6.

                                G 1 Reply Last reply 20 Nov 2022, 20:27
                                0
                                • J JonB
                                  20 Nov 2022, 18:57

                                  @gunraidan said in Occasionally get "QThread: Destroyed while thread is still running" when running multiple threads:

                                  Doing the first results in this error:

                                  <PyQt6.QtCore.QJsonValue object at 0x00000182BF9CA570>

                                  I don't see it being an error. ("qt.tlsbackend.ossl: Failed to load libssl/libcrypto." is over to you, you have had that from the start.) So that actually looks good I think, it has found a QJsonValue in pokemon_dict["abilities"], so it's working.

                                  TypeError: the JSON object must be str, bytes or bytearray, not QByteArray

                                  Then you need to convert Qt QByteArray to bytes/bytearray, however you do that from PyQt6.

                                  G Offline
                                  G Offline
                                  gunraidan
                                  wrote on 20 Nov 2022, 20:27 last edited by
                                  #15

                                  @JonB said in Occasionally get "QThread: Destroyed while thread is still running" when running multiple threads:

                                  @gunraidan said in Occasionally get "QThread: Destroyed while thread is still running" when running multiple threads:

                                  Doing the first results in this error:

                                  <PyQt6.QtCore.QJsonValue object at 0x00000182BF9CA570>

                                  I don't see it being an error. ("qt.tlsbackend.ossl: Failed to load libssl/libcrypto." is over to you, you have had that from the start.) So that actually looks good I think, it has found a QJsonValue in pokemon_dict["abilities"], so it's working.

                                  TypeError: the JSON object must be str, bytes or bytearray, not QByteArray

                                  Then you need to convert Qt QByteArray to bytes/bytearray, however you do that from PyQt6.

                                  When I type the following code:

                                      def handle_request(self, reply):
                                          er = reply.error()
                                          
                                          if er == QtNetwork.QNetworkReply.NetworkError.NoError:
                                              bytes_string = reply.readAll()
                                              pokemon_dict = QtCore.QJsonDocument.fromJson(bytes_string)
                                              pokemon_dict = pokemon_dict.object()
                                              print(pokemon_dict)
                                  

                                  This is the output:

                                  {'abilities': <PyQt6.QtCore.QJsonValue object at 0x000001EC6DE0A570>, 'base_experience': <PyQt6.QtCore.QJsonValue object at 0x000001EC6DE0A5E0>, 'forms': <PyQt6.QtCore.QJsonValue object at 0x000001EC6DE0A650>, 'game_indices': <PyQt6.QtCore.QJsonValue object at 0x000001EC6DE0A6C0>, 'height': <PyQt6.QtCore.QJsonValue object at 0x000001EC6DE0A730>, 'held_items': <PyQt6.QtCore.QJsonValue object at 0x000001EC6DE0A7A0>, 'id': <PyQt6.QtCore.QJsonValue object at 0x000001EC6DE0A810>, 'is_default': <PyQt6.QtCore.QJsonValue object at 0x000001EC6DE0A880>, 'location_area_encounters': <PyQt6.QtCore.QJsonValue object at 0x000001EC6DE0A8F0>, 'moves': <PyQt6.QtCore.QJsonValue object at 0x000001EC6DE0A960>, 'name': <PyQt6.QtCore.QJsonValue object at 0x000001EC6DE0A9D0>, 'order': <PyQt6.QtCore.QJsonValue object at 0x000001EC6DE0AA40>, 'past_types': <PyQt6.QtCore.QJsonValue object at 0x000001EC6DE0AAB0>, 'species': <PyQt6.QtCore.QJsonValue object at 0x000001EC6DE0AB20>, 'sprites': <PyQt6.QtCore.QJsonValue object at 0x000001EC6DE0AB90>, 'stats': <PyQt6.QtCore.QJsonValue object at 0x000001EC6DE0AC00>, 'types': <PyQt6.QtCore.QJsonValue object at 0x000001EC6DE0AC70>, 'weight': <PyQt6.QtCore.QJsonValue object at 0x000001EC6DE0ACE0>}
                                  

                                  So it does successfully import the data. However, unlike the keys, the values in the dictionary aren't strings but more so strange code. Is there a way to have the values be the same text string found in the api like the keys?

                                  J 2 Replies Last reply 20 Nov 2022, 20:34
                                  0
                                  • G gunraidan
                                    20 Nov 2022, 20:27

                                    @JonB said in Occasionally get "QThread: Destroyed while thread is still running" when running multiple threads:

                                    @gunraidan said in Occasionally get "QThread: Destroyed while thread is still running" when running multiple threads:

                                    Doing the first results in this error:

                                    <PyQt6.QtCore.QJsonValue object at 0x00000182BF9CA570>

                                    I don't see it being an error. ("qt.tlsbackend.ossl: Failed to load libssl/libcrypto." is over to you, you have had that from the start.) So that actually looks good I think, it has found a QJsonValue in pokemon_dict["abilities"], so it's working.

                                    TypeError: the JSON object must be str, bytes or bytearray, not QByteArray

                                    Then you need to convert Qt QByteArray to bytes/bytearray, however you do that from PyQt6.

                                    When I type the following code:

                                        def handle_request(self, reply):
                                            er = reply.error()
                                            
                                            if er == QtNetwork.QNetworkReply.NetworkError.NoError:
                                                bytes_string = reply.readAll()
                                                pokemon_dict = QtCore.QJsonDocument.fromJson(bytes_string)
                                                pokemon_dict = pokemon_dict.object()
                                                print(pokemon_dict)
                                    

                                    This is the output:

                                    {'abilities': <PyQt6.QtCore.QJsonValue object at 0x000001EC6DE0A570>, 'base_experience': <PyQt6.QtCore.QJsonValue object at 0x000001EC6DE0A5E0>, 'forms': <PyQt6.QtCore.QJsonValue object at 0x000001EC6DE0A650>, 'game_indices': <PyQt6.QtCore.QJsonValue object at 0x000001EC6DE0A6C0>, 'height': <PyQt6.QtCore.QJsonValue object at 0x000001EC6DE0A730>, 'held_items': <PyQt6.QtCore.QJsonValue object at 0x000001EC6DE0A7A0>, 'id': <PyQt6.QtCore.QJsonValue object at 0x000001EC6DE0A810>, 'is_default': <PyQt6.QtCore.QJsonValue object at 0x000001EC6DE0A880>, 'location_area_encounters': <PyQt6.QtCore.QJsonValue object at 0x000001EC6DE0A8F0>, 'moves': <PyQt6.QtCore.QJsonValue object at 0x000001EC6DE0A960>, 'name': <PyQt6.QtCore.QJsonValue object at 0x000001EC6DE0A9D0>, 'order': <PyQt6.QtCore.QJsonValue object at 0x000001EC6DE0AA40>, 'past_types': <PyQt6.QtCore.QJsonValue object at 0x000001EC6DE0AAB0>, 'species': <PyQt6.QtCore.QJsonValue object at 0x000001EC6DE0AB20>, 'sprites': <PyQt6.QtCore.QJsonValue object at 0x000001EC6DE0AB90>, 'stats': <PyQt6.QtCore.QJsonValue object at 0x000001EC6DE0AC00>, 'types': <PyQt6.QtCore.QJsonValue object at 0x000001EC6DE0AC70>, 'weight': <PyQt6.QtCore.QJsonValue object at 0x000001EC6DE0ACE0>}
                                    

                                    So it does successfully import the data. However, unlike the keys, the values in the dictionary aren't strings but more so strange code. Is there a way to have the values be the same text string found in the api like the keys?

                                    J Online
                                    J Online
                                    JonB
                                    wrote on 20 Nov 2022, 20:34 last edited by JonB
                                    #16

                                    @gunraidan
                                    You have to read the Qt QJson... classes documentation and write the code. Btw did you try to see if your pokemon_dict["abilities"][0]['ability']['name'] works?

                                    From Python you might be more comfortable getting the json module working. It may integrate more smoothly in Python than the Qt one, if the Qt one doesn't work with your pokemon_dict["abilities"][0]['ability']['name'].

                                    G 1 Reply Last reply 21 Nov 2022, 01:06
                                    0
                                    • J JonB
                                      20 Nov 2022, 20:34

                                      @gunraidan
                                      You have to read the Qt QJson... classes documentation and write the code. Btw did you try to see if your pokemon_dict["abilities"][0]['ability']['name'] works?

                                      From Python you might be more comfortable getting the json module working. It may integrate more smoothly in Python than the Qt one, if the Qt one doesn't work with your pokemon_dict["abilities"][0]['ability']['name'].

                                      G Offline
                                      G Offline
                                      gunraidan
                                      wrote on 21 Nov 2022, 01:06 last edited by
                                      #17

                                      @JonB said in Occasionally get "QThread: Destroyed while thread is still running" when running multiple threads:

                                      @gunraidan
                                      You have to read the Qt QJson... classes documentation and write the code. Btw did you try to see if your pokemon_dict["abilities"][0]['ability']['name'] works?

                                      From Python you might be more comfortable getting the json module working. It may integrate more smoothly in Python than the Qt one, if the Qt one doesn't work with your pokemon_dict["abilities"][0]['ability']['name'].

                                      This is embarrassing but I just realized I quoted you before without putting my code in.
                                      It strongly gives the impression I'm not putting in the effort, which I don't think is accurate.

                                      I came up with the following code:

                                          def handle_request(self, reply):
                                              er = reply.error()
                                              
                                              if er == QtNetwork.QNetworkReply.NetworkError.NoError:
                                      
                                                  bytes_string = reply.readAll()
                                                  pokemon_dict = json.loads(bytes_string)
                                                  x = QByteArray(pokemon_dict["abilities"][0]['ability']['name'])
                                                  print(x)
                                      

                                      In my head the json.loads will load the response into json format and then x will result in that part of the code being transferred to bytes so Python can read it.

                                      However, I still get the same error:

                                      Traceback (most recent call last):
                                        File "c:\Users\Nader\OneDrive\Documents\Coding\Python\TestNetwork.py", line 44, in handle_request
                                          bytes_string = json.loads(reply.readAll())
                                        File "C:\Users\Nader\AppData\Local\Programs\Python\Python310\lib\json\__init__.py", line 339, in loads
                                          raise TypeError(f'the JSON object must be str, bytes or bytearray, '
                                      TypeError: the JSON object must be str, bytes or bytearray, not QByteArray
                                      

                                      I have gone to the documentation here, but it lists simply the function and no examples of QJson in use (outside of a saved game load which isn't much like I'm doing.)

                                      J 1 Reply Last reply 21 Nov 2022, 09:36
                                      0
                                      • G gunraidan
                                        21 Nov 2022, 01:06

                                        @JonB said in Occasionally get "QThread: Destroyed while thread is still running" when running multiple threads:

                                        @gunraidan
                                        You have to read the Qt QJson... classes documentation and write the code. Btw did you try to see if your pokemon_dict["abilities"][0]['ability']['name'] works?

                                        From Python you might be more comfortable getting the json module working. It may integrate more smoothly in Python than the Qt one, if the Qt one doesn't work with your pokemon_dict["abilities"][0]['ability']['name'].

                                        This is embarrassing but I just realized I quoted you before without putting my code in.
                                        It strongly gives the impression I'm not putting in the effort, which I don't think is accurate.

                                        I came up with the following code:

                                            def handle_request(self, reply):
                                                er = reply.error()
                                                
                                                if er == QtNetwork.QNetworkReply.NetworkError.NoError:
                                        
                                                    bytes_string = reply.readAll()
                                                    pokemon_dict = json.loads(bytes_string)
                                                    x = QByteArray(pokemon_dict["abilities"][0]['ability']['name'])
                                                    print(x)
                                        

                                        In my head the json.loads will load the response into json format and then x will result in that part of the code being transferred to bytes so Python can read it.

                                        However, I still get the same error:

                                        Traceback (most recent call last):
                                          File "c:\Users\Nader\OneDrive\Documents\Coding\Python\TestNetwork.py", line 44, in handle_request
                                            bytes_string = json.loads(reply.readAll())
                                          File "C:\Users\Nader\AppData\Local\Programs\Python\Python310\lib\json\__init__.py", line 339, in loads
                                            raise TypeError(f'the JSON object must be str, bytes or bytearray, '
                                        TypeError: the JSON object must be str, bytes or bytearray, not QByteArray
                                        

                                        I have gone to the documentation here, but it lists simply the function and no examples of QJson in use (outside of a saved game load which isn't much like I'm doing.)

                                        J Online
                                        J Online
                                        JonB
                                        wrote on 21 Nov 2022, 09:36 last edited by
                                        #18

                                        @gunraidan said in Occasionally get "QThread: Destroyed while thread is still running" when running multiple threads:

                                        I have gone to the documentation here, but it lists simply the function and no examples of QJson in use (outside of a saved game load which isn't much like I'm doing.)

                                        Well, that's all you get!

                                        You have attempted to change your code in the light of the error, but unfortunately not the right thing! Please read the message carefully. First:

                                        File "c:\Users\Nader\OneDrive\Documents\Coding\Python\TestNetwork.py", line 44, in handle_request

                                        bytes_string = json.loads(reply.readAll())
                                        

                                        Since that clearly shows bytes_string = json.loads(reply.readAll()) while you claim your code has pokemon_dict = json.loads(bytes_string), how can you get that error message from the code you show? I can only conclude that is not the code you have to cause that message. Please don't do this, it makes it very frustrating when people try to help and code/messages are not actually what you claim they are.

                                        Second:

                                        File "C:\Users\Nader\AppData\Local\Programs\Python\Python310\lib\json_init_.py", line 339, in loads

                                        raise TypeError(f'the JSON object must be str, bytes or bytearray, '
                                        

                                        TypeError: the JSON object must be str, bytes or bytearray, not QByteArray

                                        Read the error message. It tells you it was in the json.loads(something) call. It tells you it requires the parameter to be "str, bytes or bytearray", but that it is actually "QByteArray" (as returned from readAll()). And it is apparently not prepared to convert for you. Hence I wrote earlier:

                                        TypeError: the JSON object must be str, bytes or bytearray, not QByteArray

                                        Then you need to convert Qt QByteArray to bytes/bytearray, however you do that from PyQt6.

                                        You were supposed to Google to find out how to do that. I don't, I don't use Python. Your putting in x = QByteArray(...) after the json.loads() call is not going to address this, you need to change what you pass to json.loads().

                                        I will have a go at producing something in next post.....

                                        1 Reply Last reply
                                        1
                                        • G gunraidan
                                          20 Nov 2022, 20:27

                                          @JonB said in Occasionally get "QThread: Destroyed while thread is still running" when running multiple threads:

                                          @gunraidan said in Occasionally get "QThread: Destroyed while thread is still running" when running multiple threads:

                                          Doing the first results in this error:

                                          <PyQt6.QtCore.QJsonValue object at 0x00000182BF9CA570>

                                          I don't see it being an error. ("qt.tlsbackend.ossl: Failed to load libssl/libcrypto." is over to you, you have had that from the start.) So that actually looks good I think, it has found a QJsonValue in pokemon_dict["abilities"], so it's working.

                                          TypeError: the JSON object must be str, bytes or bytearray, not QByteArray

                                          Then you need to convert Qt QByteArray to bytes/bytearray, however you do that from PyQt6.

                                          When I type the following code:

                                              def handle_request(self, reply):
                                                  er = reply.error()
                                                  
                                                  if er == QtNetwork.QNetworkReply.NetworkError.NoError:
                                                      bytes_string = reply.readAll()
                                                      pokemon_dict = QtCore.QJsonDocument.fromJson(bytes_string)
                                                      pokemon_dict = pokemon_dict.object()
                                                      print(pokemon_dict)
                                          

                                          This is the output:

                                          {'abilities': <PyQt6.QtCore.QJsonValue object at 0x000001EC6DE0A570>, 'base_experience': <PyQt6.QtCore.QJsonValue object at 0x000001EC6DE0A5E0>, 'forms': <PyQt6.QtCore.QJsonValue object at 0x000001EC6DE0A650>, 'game_indices': <PyQt6.QtCore.QJsonValue object at 0x000001EC6DE0A6C0>, 'height': <PyQt6.QtCore.QJsonValue object at 0x000001EC6DE0A730>, 'held_items': <PyQt6.QtCore.QJsonValue object at 0x000001EC6DE0A7A0>, 'id': <PyQt6.QtCore.QJsonValue object at 0x000001EC6DE0A810>, 'is_default': <PyQt6.QtCore.QJsonValue object at 0x000001EC6DE0A880>, 'location_area_encounters': <PyQt6.QtCore.QJsonValue object at 0x000001EC6DE0A8F0>, 'moves': <PyQt6.QtCore.QJsonValue object at 0x000001EC6DE0A960>, 'name': <PyQt6.QtCore.QJsonValue object at 0x000001EC6DE0A9D0>, 'order': <PyQt6.QtCore.QJsonValue object at 0x000001EC6DE0AA40>, 'past_types': <PyQt6.QtCore.QJsonValue object at 0x000001EC6DE0AAB0>, 'species': <PyQt6.QtCore.QJsonValue object at 0x000001EC6DE0AB20>, 'sprites': <PyQt6.QtCore.QJsonValue object at 0x000001EC6DE0AB90>, 'stats': <PyQt6.QtCore.QJsonValue object at 0x000001EC6DE0AC00>, 'types': <PyQt6.QtCore.QJsonValue object at 0x000001EC6DE0AC70>, 'weight': <PyQt6.QtCore.QJsonValue object at 0x000001EC6DE0ACE0>}
                                          

                                          So it does successfully import the data. However, unlike the keys, the values in the dictionary aren't strings but more so strange code. Is there a way to have the values be the same text string found in the api like the keys?

                                          J Online
                                          J Online
                                          JonB
                                          wrote on 21 Nov 2022, 10:18 last edited by JonB
                                          #19

                                          @gunraidan
                                          Here is the code (tested PyQt5) for the two possible approaches:

                                          import json
                                          
                                          from PyQt5 import QtCore
                                          
                                          if __name__ == '__main__':
                                              # I put your sample JSON into a file, since they are not arriving at my serial port
                                              f = QtCore.QFile("file.json")
                                              if not f.open(QtCore.QIODevice.ReadOnly):
                                                  raise "Whoops"
                                              # following line's `readAll()` returns `QByteArray` type, just like when you read from serial port
                                              qbytearray = f.readAll()
                                              f.close()
                                          
                                              # Use `json.loads()` approach:
                                              # next line converts Qt `QByteArray` type to Python `bytes` type...
                                              pythonbytearray = bytes(qbytearray)
                                              # ...so that now it is acceptable to `json.loads(...)`
                                              pokemon_dict = json.loads(pythonbytearray)
                                              x = pokemon_dict["abilities"][0]['ability']['name']
                                              # next line prints `static`, which must be the value there
                                              print(x)
                                          
                                              # Use `QtCore.QJson...` approach:
                                              pokemon_dict = QtCore.QJsonDocument.fromJson(qbytearray)
                                              x = pokemon_dict["abilities"][0]['ability']['name'].toString()
                                              # next line prints `static`, which must be the value there
                                              print(x)
                                          
                                          

                                          As you can see, all you had to discover for Python/PyQt json.loads(...) is that you can convert a Qt QByteArray to a Python bytes array via bytes(qByteArrayValue).

                                          Use either one of these approaches. The json modules is slightly better integrated into Python than the Qt QJson... classes (e.g. note the QJson expression requires the toString() at the end, but the json one does not), so you may prefer to use the former. On the other hand, while json.loads() requires converting a QByteArray to a bytes, QJsonDocument.fromJson() does not.

                                          G 1 Reply Last reply 21 Nov 2022, 21:45
                                          2
                                          • J JonB
                                            21 Nov 2022, 10:18

                                            @gunraidan
                                            Here is the code (tested PyQt5) for the two possible approaches:

                                            import json
                                            
                                            from PyQt5 import QtCore
                                            
                                            if __name__ == '__main__':
                                                # I put your sample JSON into a file, since they are not arriving at my serial port
                                                f = QtCore.QFile("file.json")
                                                if not f.open(QtCore.QIODevice.ReadOnly):
                                                    raise "Whoops"
                                                # following line's `readAll()` returns `QByteArray` type, just like when you read from serial port
                                                qbytearray = f.readAll()
                                                f.close()
                                            
                                                # Use `json.loads()` approach:
                                                # next line converts Qt `QByteArray` type to Python `bytes` type...
                                                pythonbytearray = bytes(qbytearray)
                                                # ...so that now it is acceptable to `json.loads(...)`
                                                pokemon_dict = json.loads(pythonbytearray)
                                                x = pokemon_dict["abilities"][0]['ability']['name']
                                                # next line prints `static`, which must be the value there
                                                print(x)
                                            
                                                # Use `QtCore.QJson...` approach:
                                                pokemon_dict = QtCore.QJsonDocument.fromJson(qbytearray)
                                                x = pokemon_dict["abilities"][0]['ability']['name'].toString()
                                                # next line prints `static`, which must be the value there
                                                print(x)
                                            
                                            

                                            As you can see, all you had to discover for Python/PyQt json.loads(...) is that you can convert a Qt QByteArray to a Python bytes array via bytes(qByteArrayValue).

                                            Use either one of these approaches. The json modules is slightly better integrated into Python than the Qt QJson... classes (e.g. note the QJson expression requires the toString() at the end, but the json one does not), so you may prefer to use the former. On the other hand, while json.loads() requires converting a QByteArray to a bytes, QJsonDocument.fromJson() does not.

                                            G Offline
                                            G Offline
                                            gunraidan
                                            wrote on 21 Nov 2022, 21:45 last edited by
                                            #20

                                            @JonB said in Occasionally get "QThread: Destroyed while thread is still running" when running multiple threads:

                                            @gunraidan
                                            Here is the code (tested PyQt5) for the two possible approaches:

                                            import json
                                            
                                            from PyQt5 import QtCore
                                            
                                            if __name__ == '__main__':
                                                # I put your sample JSON into a file, since they are not arriving at my serial port
                                                f = QtCore.QFile("file.json")
                                                if not f.open(QtCore.QIODevice.ReadOnly):
                                                    raise "Whoops"
                                                # following line's `readAll()` returns `QByteArray` type, just like when you read from serial port
                                                qbytearray = f.readAll()
                                                f.close()
                                            
                                                # Use `json.loads()` approach:
                                                # next line converts Qt `QByteArray` type to Python `bytes` type...
                                                pythonbytearray = bytes(qbytearray)
                                                # ...so that now it is acceptable to `json.loads(...)`
                                                pokemon_dict = json.loads(pythonbytearray)
                                                x = pokemon_dict["abilities"][0]['ability']['name']
                                                # next line prints `static`, which must be the value there
                                                print(x)
                                            
                                                # Use `QtCore.QJson...` approach:
                                                pokemon_dict = QtCore.QJsonDocument.fromJson(qbytearray)
                                                x = pokemon_dict["abilities"][0]['ability']['name'].toString()
                                                # next line prints `static`, which must be the value there
                                                print(x)
                                            
                                            

                                            As you can see, all you had to discover for Python/PyQt json.loads(...) is that you can convert a Qt QByteArray to a Python bytes array via bytes(qByteArrayValue).

                                            Use either one of these approaches. The json modules is slightly better integrated into Python than the Qt QJson... classes (e.g. note the QJson expression requires the toString() at the end, but the json one does not), so you may prefer to use the former. On the other hand, while json.loads() requires converting a QByteArray to a bytes, QJsonDocument.fromJson() does not.

                                            Thank you.

                                            The following code:

                                            pokemon_dict = []
                                            json2qt = QtCore.QJsonDocument.fromJson
                                            
                                            class MainWindow(QWidget):  
                                                def __init__ (self):
                                                    super().__init__()
                                                    self.title = "Window"
                                                    self.left = 200
                                                    self.top = 300
                                                    self.width = 300
                                                    self.height = 300
                                                    self.setWindowTitle(self.title)
                                                    self.setGeometry(self.left, self.top,self.width, self.height)
                                            
                                                    self.start_button()
                                                    self.show()
                                                    
                                                def start_button(self):
                                                    self.s_button = QtWidgets.QPushButton(self)
                                                    self.s_button.setText('Start')
                                                    self.s_button.clicked.connect(self.site_request)
                                                    
                                                
                                                def site_request(self):
                                                    url = 'https://pokeapi.co/api/v2/pokemon/pikachu'
                                                    req = QtNetwork.QNetworkRequest(QUrl(url))
                                                    
                                                    self.nam = QtNetwork.QNetworkAccessManager()
                                                    self.nam.finished.connect(self.handle_request)
                                                    self.nam.get(req)
                                                    
                                                def handle_request(self, reply):
                                                    er = reply.error()
                                                    
                                                    if er == QtNetwork.QNetworkReply.NetworkError.NoError:
                                                        qbyte = reply.readAll()
                                                        pokemon_dict = json2qt(qbyte)
                                                        x = pokemon_dict["abilities"][0]['ability']['name'].toString()
                                                        print(x)
                                                    else:
                                                        print ("Error")
                                                        print(reply.errorString())
                                                    
                                                    
                                            if __name__ == '__main__':        
                                                app = QApplication(sys.argv) 
                                                ex = MainWindow()        
                                                code = app.exec()
                                                sys.exit(code)
                                            

                                            Works as it prints the name: "static".

                                            Thank you for all your help!

                                            One more thing, that you don't have to answer. Do you have any idea what the qt.tlsbackend.ossl: Failed to load libssl/libcrypto. could be? It doesn't effect the program at all and I assume has to do with the api's security not being picked up since it references "ssl"?

                                            Doing some research of what "libssl and libcrypto are took me to this page.

                                            jsulmJ 1 Reply Last reply 22 Nov 2022, 06:25
                                            0

                                            1/25

                                            16 Nov 2022, 07:04

                                            • Login

                                            • Login or register to search.
                                            1 out of 25
                                            • First post
                                              1/25
                                              Last post
                                            0
                                            • Categories
                                            • Recent
                                            • Tags
                                            • Popular
                                            • Users
                                            • Groups
                                            • Search
                                            • Get Qt Extensions
                                            • Unsolved