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. segmentation fault (core dumped) when indexing items in a QListWidget to access an item using its data (int) using for loop in PySide6 6.8.1.1
QtWS25 Last Chance

segmentation fault (core dumped) when indexing items in a QListWidget to access an item using its data (int) using for loop in PySide6 6.8.1.1

Scheduled Pinned Locked Moved Solved Qt for Python
5 Posts 3 Posters 173 Views
  • 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.
  • P Offline
    P Offline
    piyeld
    wrote on last edited by
    #1

    Greetings!
    I am currently working in a photobooth program for our school organization. This past few days, I am trying to solve a segmentation fault that occurs when I try to iterate the items in a QListWidget using a for loop.

    def find_item_by_value(self, value):
            for index in range(self.list.count()):
                print(self.list.item(index), type(self.list.item(index))) 
                faulthandler.enable()
                list_item = self.list.item(index) # segmentation fault error in here 
                if list_item is None:
                    print(f"Item at index {index} is None")
                    continue
    
                item_data = list_item.data(Qt.UserRole)
                if not item_data or not isinstance(item_data, dict):
                    print(f"Invalid data at index {index}: {item_data}")
                    continue         
    
                if list_item.data(Qt.UserRole)["queue_num"] == value:
                    return list_item
            return None
    

    ic() is the icecream library
    The output of the ic() statement is:

    ic| self.list.item(index): <PySide6.QtWidgets.QListWidgetItem object at 0x7a1120dc4780>
        type(self.list.item(index)): <class 'PySide6.QtWidgets.QListWidgetItem'>
    

    the output of faulthandler.enable()

    Fatal Python error: Segmentation fault
    
    Thread 0x00007a11011fe6c0 (most recent call first):
      File "/home/fieled/Projects/FastPhoto/src/components/print_service.py", line 19 in call
      File "/home/fieled/Projects/FastPhoto/src/components/worker.py", line 60 in print_img
      File "/home/fieled/Projects/FastPhoto/src/components/worker.py", line 56 in process_image
      File "/home/fieled/Projects/FastPhoto/src/components/worker.py", line 38 in run
    
    Current thread 0x00007a112b9f4bc0 (most recent call first):
      File "/home/fieled/Projects/FastPhoto/src/components/queue_gui.py", line 76 in find_item_by_value
      File "/home/fieled/Projects/FastPhoto/src/components/queue_gui.py", line 86 in update_progress_to_specific_queue_num
      File "/home/fieled/Projects/FastPhoto/src/main.py", line 51 in <module>
    
    Extension modules: shiboken6.Shiboken, PySide6.QtCore, PySide6.QtGui, PySide6.QtWidgets, PySide6.QtNetwork, PySide6.QtMultimedia, PySide6.QtMultimediaWidgets, PIL._imaging, _cffi_backend, PySide6.QtPrintSupport, PySide6.QtPdf, PIL._imagingmath (total: 12)
    

    Python does not provide any stack trace, and the shell only outputs

    zsh: segmentation fault (core dumped)  python main.py
    

    Then the program ends.

    So I am currently confused why it has that error, I inspected the variables before the segmentation fault, and I did not see anything that would cause it (or atleast in my current knowledge). These are the variables when I debug it.

    ic| self.list.item(index): <PySide6.QtWidgets.QListWidgetItem object at 0x7f5a1012a0c0>
        type(self.list.item(index)): <class 'PySide6.QtWidgets.QListWidgetItem'>
        index: 0
        self.list.count(): 2
        value: 1
    

    The program currently has two threads, MainThread and the WorkerThread. The workerthread is primarily used for image manipulation tasks and online upload. I also use queues so that work is automatically added and run.

    WorkerThread

    from PySide6.QtCore import QThread, Signal
    import queue, os
    from icecream import ic
    from components.upload_worker import UploadWorker
    from components.print_service import PrintService
    
    class WorkerThread(QThread):
        progress = Signal(str)  # Signal to communicate progress updates to the GUI
        queue_number_notifier = Signal(int)
        current_args_of_operation = Signal(dict)
    
        def __init__(self, work_queue):
            super().__init__()
            self.work_queue = work_queue
            self._is_running = True
            self.upload_worker = UploadWorker()
            self.upload_worker.output.connect(self.print_img)
            self.upload_worker.errorSig.connect(self.notify_error)
            self.print_service = PrintService()
            self.current_args = None
    
        def run(self):
            try:
                while self._is_running:
                    try:
                        # Attempt to get a task from the queue with a timeout
                        self.args = self.work_queue.get(timeout=1)
                    except queue.Empty:
                        continue  # No task available, continue the loop
    
                    # Notify the GUI of the queue number
                    queue_num = self.args["queue_num"]
                    self.queue_number_notifier.emit(queue_num)
                    self.current_args = self.args
    
                    ic(self.args, os.path.basename(__file__))
                    # Process the task
                    self.process_image(self.args)
    
                    # Mark the task as done
                    self.work_queue.task_done()
            except Exception as e:
                ic(e, os.path.basename(__file__))
    
        def process_image(self, args):
            isUploadOnline = args["isUploadOnline"]
            self.printer_instance = args["printer_instance"]
            img_path = args["path_to_img"]
    
            # Initiation of Uploading and/or printing tasks
            if isUploadOnline:
                self.progress.emit("Uploading")
                self.upload_worker.upload_and_overlay(img_path)
            else:
                self.progress.emit("Printing")
                self.print_img(img_path)
    
        def print_img(self, img_path:str):
            self.progress.emit("Printing")
            self.print_service.call(img_path, self.printer_instance)
            self.progress.emit("Done")
    
        def notify_error(self, err:str):
            ic(self.args == self.current_args, os.path.basename(__file__))
            self.current_args_of_operation.emit(self.args)
            self.progress.emit(err)
    
        def stop(self):
            self._is_running = False
            self.quit()
            self.wait()
    
    

    For more context, here is the trace of how a specific part of my app runs starting from the button that triggers the work. And here's the github repo of the app, if needed.

    ic| print_options.py:75 in process_to_queue_worker() at 17:34:09.529
    ic| queue_worker.py:44 in addWork() at 17:34:09.530
    ic| queue_worker.py:51 in addWork() at 17:34:09.532
    ic| worker.py:37 in run() at 17:34:09.535
    ic| self.args: {'frame_name': 'ps',
                    'isUploadOnline': True,
                    'name': 'sigsegv',
                    'path_to_img': '/home/fieled/Pictures/FastPhotoCaptures/Processed/photostrip-250331-173355.png',
                    'printer_instance': <PySide6.QtPrintSupport.QPrinter object at 0x74c7ac43e640>,
                    'queue_num': 1,
                    'size_str': '2.0x6.0'}
        os.path.basename(__file__): 'worker.py'
    ic| worker.py:54 in process_image() at 17:34:09.552
    ic| upload_worker.py:33 in upload_and_overlay() at 17:34:09.555
    ic| upload_worker.py:56 in upload_photo() at 17:34:09.557
    ic| queue_worker.py:39 in setStatus() at 17:34:09.709
    ic| queue_gui.py:88 in update_progress_to_specific_queue_num() at 17:34:09.761
    ic| queue_gui.py:68 in find_item_by_value() at 17:34:09.762
    ic| self.list.item(index): <PySide6.QtWidgets.QListWidgetItem object at 0x74c7ac41a9c0>
        type(self.list.item(index)): <class 'PySide6.QtWidgets.QListWidgetItem'>
        index: 0
        self.list.count(): 2
        value: 1
    ic| queue_gui.py:72 in find_item_by_value() at 17:34:09.767
    Fatal Python error: Segmentation fault
    
    Thread 0x000074c7ae3fe6c0 (most recent call first):
      File "/home/fieled/Projects/FastPhoto/.venv/lib/python3.13/site-packages/httplib2/__init__.py", line 183 in _build_ssl_context
      File "/home/fieled/Projects/FastPhoto/.venv/lib/python3.13/site-packages/httplib2/__init__.py", line 1100 in __init__
      File "/home/fieled/Projects/FastPhoto/.venv/lib/python3.13/site-packages/httplib2/__init__.py", line 1581 in request
      File "/home/fieled/Projects/FastPhoto/.venv/lib/python3.13/site-packages/google_auth_httplib2.py", line 119 in __call__
      File "/home/fieled/Projects/FastPhoto/.venv/lib/python3.13/site-packages/google/oauth2/_client.py", line 192 in _token_endpoint_request_no_throw
      File "/home/fieled/Projects/FastPhoto/.venv/lib/python3.13/site-packages/google/oauth2/_client.py", line 259 in _token_endpoint_request
      File "/home/fieled/Projects/FastPhoto/.venv/lib/python3.13/site-packages/google/oauth2/_client.py", line 299 in jwt_grant
      File "/home/fieled/Projects/FastPhoto/.venv/lib/python3.13/site-packages/google/oauth2/service_account.py", line 448 in refresh
      File "/home/fieled/Projects/FastPhoto/.venv/lib/python3.13/site-packages/google/auth/credentials.py", line 202 in _blocking_refresh
      File "/home/fieled/Projects/FastPhoto/.venv/lib/python3.13/site-packages/google/auth/credentials.py", line 239 in before_request
      File "/home/fieled/Projects/FastPhoto/.venv/lib/python3.13/site-packages/google_auth_httplib2.py", line 209 in request
      File "/home/fieled/Projects/FastPhoto/.venv/lib/python3.13/site-packages/googleapiclient/http.py", line 190 in _retry_request
      File "/home/fieled/Projects/FastPhoto/.venv/lib/python3.13/site-packages/googleapiclient/http.py", line 922 in execute
      File "/home/fieled/Projects/FastPhoto/.venv/lib/python3.13/site-packages/googleapiclient/_helpers.py", line 131 in positional_wrapper
      File "/home/fieled/Projects/FastPhoto/src/components/upload_worker.py", line 72 in upload_photo
      File "/home/fieled/Projects/FastPhoto/src/components/upload_worker.py", line 39 in upload_and_overlay
      File "/home/fieled/Projects/FastPhoto/src/components/worker.py", line 56 in process_image
      File "/home/fieled/Projects/FastPhoto/src/components/worker.py", line 40 in run
    
    Current thread 0x000074c7dc7adbc0 (most recent call first):
      File "/home/fieled/Projects/FastPhoto/src/components/queue_gui.py", line 78 in find_item_by_value
      File "/home/fieled/Projects/FastPhoto/src/components/queue_gui.py", line 89 in update_progress_to_specific_queue_num
      File "/home/fieled/Projects/FastPhoto/src/main.py", line 51 in <module>
    
    Extension modules: shiboken6.Shiboken, PySide6.QtCore, PySide6.QtGui, PySide6.QtWidgets, PySide6.QtNetwork, PySide6.QtMultimedia, PySide6.QtMultimediaWidgets, PIL._imaging, _cffi_backend, PySide6.QtPrintSupport, PySide6.QtPdf, PIL._imagingmath (total: 12)
    

    Please help me.

    Additional Information:
    Distribution: Arch Linux
    VSCode Version: 1.98.2
    Kernel Version: Linux x64 6.13.8-zen1-1-zen
    PySide6 Version: 6.8.1.1

    JonBJ 1 Reply Last reply
    0
    • P piyeld

      Greetings!
      I am currently working in a photobooth program for our school organization. This past few days, I am trying to solve a segmentation fault that occurs when I try to iterate the items in a QListWidget using a for loop.

      def find_item_by_value(self, value):
              for index in range(self.list.count()):
                  print(self.list.item(index), type(self.list.item(index))) 
                  faulthandler.enable()
                  list_item = self.list.item(index) # segmentation fault error in here 
                  if list_item is None:
                      print(f"Item at index {index} is None")
                      continue
      
                  item_data = list_item.data(Qt.UserRole)
                  if not item_data or not isinstance(item_data, dict):
                      print(f"Invalid data at index {index}: {item_data}")
                      continue         
      
                  if list_item.data(Qt.UserRole)["queue_num"] == value:
                      return list_item
              return None
      

      ic() is the icecream library
      The output of the ic() statement is:

      ic| self.list.item(index): <PySide6.QtWidgets.QListWidgetItem object at 0x7a1120dc4780>
          type(self.list.item(index)): <class 'PySide6.QtWidgets.QListWidgetItem'>
      

      the output of faulthandler.enable()

      Fatal Python error: Segmentation fault
      
      Thread 0x00007a11011fe6c0 (most recent call first):
        File "/home/fieled/Projects/FastPhoto/src/components/print_service.py", line 19 in call
        File "/home/fieled/Projects/FastPhoto/src/components/worker.py", line 60 in print_img
        File "/home/fieled/Projects/FastPhoto/src/components/worker.py", line 56 in process_image
        File "/home/fieled/Projects/FastPhoto/src/components/worker.py", line 38 in run
      
      Current thread 0x00007a112b9f4bc0 (most recent call first):
        File "/home/fieled/Projects/FastPhoto/src/components/queue_gui.py", line 76 in find_item_by_value
        File "/home/fieled/Projects/FastPhoto/src/components/queue_gui.py", line 86 in update_progress_to_specific_queue_num
        File "/home/fieled/Projects/FastPhoto/src/main.py", line 51 in <module>
      
      Extension modules: shiboken6.Shiboken, PySide6.QtCore, PySide6.QtGui, PySide6.QtWidgets, PySide6.QtNetwork, PySide6.QtMultimedia, PySide6.QtMultimediaWidgets, PIL._imaging, _cffi_backend, PySide6.QtPrintSupport, PySide6.QtPdf, PIL._imagingmath (total: 12)
      

      Python does not provide any stack trace, and the shell only outputs

      zsh: segmentation fault (core dumped)  python main.py
      

      Then the program ends.

      So I am currently confused why it has that error, I inspected the variables before the segmentation fault, and I did not see anything that would cause it (or atleast in my current knowledge). These are the variables when I debug it.

      ic| self.list.item(index): <PySide6.QtWidgets.QListWidgetItem object at 0x7f5a1012a0c0>
          type(self.list.item(index)): <class 'PySide6.QtWidgets.QListWidgetItem'>
          index: 0
          self.list.count(): 2
          value: 1
      

      The program currently has two threads, MainThread and the WorkerThread. The workerthread is primarily used for image manipulation tasks and online upload. I also use queues so that work is automatically added and run.

      WorkerThread

      from PySide6.QtCore import QThread, Signal
      import queue, os
      from icecream import ic
      from components.upload_worker import UploadWorker
      from components.print_service import PrintService
      
      class WorkerThread(QThread):
          progress = Signal(str)  # Signal to communicate progress updates to the GUI
          queue_number_notifier = Signal(int)
          current_args_of_operation = Signal(dict)
      
          def __init__(self, work_queue):
              super().__init__()
              self.work_queue = work_queue
              self._is_running = True
              self.upload_worker = UploadWorker()
              self.upload_worker.output.connect(self.print_img)
              self.upload_worker.errorSig.connect(self.notify_error)
              self.print_service = PrintService()
              self.current_args = None
      
          def run(self):
              try:
                  while self._is_running:
                      try:
                          # Attempt to get a task from the queue with a timeout
                          self.args = self.work_queue.get(timeout=1)
                      except queue.Empty:
                          continue  # No task available, continue the loop
      
                      # Notify the GUI of the queue number
                      queue_num = self.args["queue_num"]
                      self.queue_number_notifier.emit(queue_num)
                      self.current_args = self.args
      
                      ic(self.args, os.path.basename(__file__))
                      # Process the task
                      self.process_image(self.args)
      
                      # Mark the task as done
                      self.work_queue.task_done()
              except Exception as e:
                  ic(e, os.path.basename(__file__))
      
          def process_image(self, args):
              isUploadOnline = args["isUploadOnline"]
              self.printer_instance = args["printer_instance"]
              img_path = args["path_to_img"]
      
              # Initiation of Uploading and/or printing tasks
              if isUploadOnline:
                  self.progress.emit("Uploading")
                  self.upload_worker.upload_and_overlay(img_path)
              else:
                  self.progress.emit("Printing")
                  self.print_img(img_path)
      
          def print_img(self, img_path:str):
              self.progress.emit("Printing")
              self.print_service.call(img_path, self.printer_instance)
              self.progress.emit("Done")
      
          def notify_error(self, err:str):
              ic(self.args == self.current_args, os.path.basename(__file__))
              self.current_args_of_operation.emit(self.args)
              self.progress.emit(err)
      
          def stop(self):
              self._is_running = False
              self.quit()
              self.wait()
      
      

      For more context, here is the trace of how a specific part of my app runs starting from the button that triggers the work. And here's the github repo of the app, if needed.

      ic| print_options.py:75 in process_to_queue_worker() at 17:34:09.529
      ic| queue_worker.py:44 in addWork() at 17:34:09.530
      ic| queue_worker.py:51 in addWork() at 17:34:09.532
      ic| worker.py:37 in run() at 17:34:09.535
      ic| self.args: {'frame_name': 'ps',
                      'isUploadOnline': True,
                      'name': 'sigsegv',
                      'path_to_img': '/home/fieled/Pictures/FastPhotoCaptures/Processed/photostrip-250331-173355.png',
                      'printer_instance': <PySide6.QtPrintSupport.QPrinter object at 0x74c7ac43e640>,
                      'queue_num': 1,
                      'size_str': '2.0x6.0'}
          os.path.basename(__file__): 'worker.py'
      ic| worker.py:54 in process_image() at 17:34:09.552
      ic| upload_worker.py:33 in upload_and_overlay() at 17:34:09.555
      ic| upload_worker.py:56 in upload_photo() at 17:34:09.557
      ic| queue_worker.py:39 in setStatus() at 17:34:09.709
      ic| queue_gui.py:88 in update_progress_to_specific_queue_num() at 17:34:09.761
      ic| queue_gui.py:68 in find_item_by_value() at 17:34:09.762
      ic| self.list.item(index): <PySide6.QtWidgets.QListWidgetItem object at 0x74c7ac41a9c0>
          type(self.list.item(index)): <class 'PySide6.QtWidgets.QListWidgetItem'>
          index: 0
          self.list.count(): 2
          value: 1
      ic| queue_gui.py:72 in find_item_by_value() at 17:34:09.767
      Fatal Python error: Segmentation fault
      
      Thread 0x000074c7ae3fe6c0 (most recent call first):
        File "/home/fieled/Projects/FastPhoto/.venv/lib/python3.13/site-packages/httplib2/__init__.py", line 183 in _build_ssl_context
        File "/home/fieled/Projects/FastPhoto/.venv/lib/python3.13/site-packages/httplib2/__init__.py", line 1100 in __init__
        File "/home/fieled/Projects/FastPhoto/.venv/lib/python3.13/site-packages/httplib2/__init__.py", line 1581 in request
        File "/home/fieled/Projects/FastPhoto/.venv/lib/python3.13/site-packages/google_auth_httplib2.py", line 119 in __call__
        File "/home/fieled/Projects/FastPhoto/.venv/lib/python3.13/site-packages/google/oauth2/_client.py", line 192 in _token_endpoint_request_no_throw
        File "/home/fieled/Projects/FastPhoto/.venv/lib/python3.13/site-packages/google/oauth2/_client.py", line 259 in _token_endpoint_request
        File "/home/fieled/Projects/FastPhoto/.venv/lib/python3.13/site-packages/google/oauth2/_client.py", line 299 in jwt_grant
        File "/home/fieled/Projects/FastPhoto/.venv/lib/python3.13/site-packages/google/oauth2/service_account.py", line 448 in refresh
        File "/home/fieled/Projects/FastPhoto/.venv/lib/python3.13/site-packages/google/auth/credentials.py", line 202 in _blocking_refresh
        File "/home/fieled/Projects/FastPhoto/.venv/lib/python3.13/site-packages/google/auth/credentials.py", line 239 in before_request
        File "/home/fieled/Projects/FastPhoto/.venv/lib/python3.13/site-packages/google_auth_httplib2.py", line 209 in request
        File "/home/fieled/Projects/FastPhoto/.venv/lib/python3.13/site-packages/googleapiclient/http.py", line 190 in _retry_request
        File "/home/fieled/Projects/FastPhoto/.venv/lib/python3.13/site-packages/googleapiclient/http.py", line 922 in execute
        File "/home/fieled/Projects/FastPhoto/.venv/lib/python3.13/site-packages/googleapiclient/_helpers.py", line 131 in positional_wrapper
        File "/home/fieled/Projects/FastPhoto/src/components/upload_worker.py", line 72 in upload_photo
        File "/home/fieled/Projects/FastPhoto/src/components/upload_worker.py", line 39 in upload_and_overlay
        File "/home/fieled/Projects/FastPhoto/src/components/worker.py", line 56 in process_image
        File "/home/fieled/Projects/FastPhoto/src/components/worker.py", line 40 in run
      
      Current thread 0x000074c7dc7adbc0 (most recent call first):
        File "/home/fieled/Projects/FastPhoto/src/components/queue_gui.py", line 78 in find_item_by_value
        File "/home/fieled/Projects/FastPhoto/src/components/queue_gui.py", line 89 in update_progress_to_specific_queue_num
        File "/home/fieled/Projects/FastPhoto/src/main.py", line 51 in <module>
      
      Extension modules: shiboken6.Shiboken, PySide6.QtCore, PySide6.QtGui, PySide6.QtWidgets, PySide6.QtNetwork, PySide6.QtMultimedia, PySide6.QtMultimediaWidgets, PIL._imaging, _cffi_backend, PySide6.QtPrintSupport, PySide6.QtPdf, PIL._imagingmath (total: 12)
      

      Please help me.

      Additional Information:
      Distribution: Arch Linux
      VSCode Version: 1.98.2
      Kernel Version: Linux x64 6.13.8-zen1-1-zen
      PySide6 Version: 6.8.1.1

      JonBJ Offline
      JonBJ Offline
      JonB
      wrote on last edited by
      #2

      @piyeld
      This is a lot of complex stuff. It is not clear to me what is accessed where. First things first: in a word, do you access a UI QlistWidget from your WorkerThread?

      1 Reply Last reply
      0
      • P Offline
        P Offline
        piyeld
        wrote on last edited by
        #3

        @JonB
        Thank you for replying!
        To answer your question, no.

        For clarity, this program does photobooth stuff---captures images, then puts them into a frame. The action that leads to the error starts in this function.
        print_options.py: PrintOptions.process_to_queue_worker()

        def process_to_queue_worker(self):
                path = self.frame_presets.getCurrentOverlayedImage()
                printer_name = self.printer_options.currentText()
                orientation = self.orientation_options.currentText()
                isUploadOnline = self.online_uploader.getIsUploadState()
                name = self.name_form.get_text()
                current_frame_index = self.frame_presets.getCurrentIndex()
                current_frame_name = self.frame_presets.getPresets()[current_frame_index]["name"]
        
                printer_instance = QPrinter(QPrinter.HighResolution)
                printer_instance.setPrinterName(printer_name)
                printer_instance.setPageOrientation(getattr(QPageLayout, orientation, None))
                
                custom_size = QSizeF(float(self.width_custom.text()), float(self.height_custom.text()))
                page_size = QPageSize(custom_size, QPageSize.Unit.Inch, "CustomSize")
                printer_instance.setPageSize(page_size)
        
                ic()
                self.queue_worker.addWork({
                    "path_to_img": path, 
                    "printer_instance": printer_instance, 
                    "isUploadOnline": isUploadOnline, 
                    "name": name if name else "No Name", 
                    "size_str": f'{custom_size.width()}x{custom_size.height()}',
                    "frame_name": current_frame_name
                    })
        

        This function's primary work is to collect information from other classes (which are singletons), and then put the in a dictionary that then will be sent to the self.queue_worker.addWork() function
        Moving on to the function's code
        queue_worker.py: QueueWorker.addWork() (singleton)

        def addWork(self, args:dict):
                args["queue_num"] = self.current_work_number
        
                data = [f'{args["name"]} - {args["frame_name"]} - {args["size_str"]}', args]
                self.work_added.emit(data)
                self.work_queue.put(args)
        
                self.current_work_number += 1  
        

        This function does things:

        1. adds the key queue_num into the args dict and assigns it the value of self.current_work_number
        2. creates a data variable, which will be used by a custom class, then is emitted by the signal work_added, which will be used by the queue_gui.py: add_to_list()
            def add_to_list(self, item_data: list):
                list_item = QListWidgetItem()
                item_widget = QueueItemWidget(item_data[0], item_data[1]["queue_num"])
                list_item.setData(Qt.UserRole, item_data[1])
                list_item.setSizeHint(item_widget.sizeHint())
                self.list.addItem(list_item)
                self.list.setItemWidget(list_item, item_widget)
        
        1. the args dict is then added to the work_queue, which will later be processed by the WorkerThread
        2. the var self.current_work_number will then be incremented, so that another work will use the variable

        worker.py: WorkerThread

        def run(self):
                try:
                    while self._is_running:
                        try:
                            ic()
                            # Attempt to get a task from the queue with a timeout
                            self.args = self.work_queue.get(timeout=1)
                        except queue.Empty:
                            continue  # No task available, continue the loop
        
                        # Notify the GUI of the queue number
                        queue_num = self.args["queue_num"]
                        self.queue_number_notifier.emit(queue_num)
                        self.current_args = self.args
        
                        ic()
                        ic(self.args, os.path.basename(__file__))
                        # Process the task
                        self.process_image(self.args)
        
                        # Mark the task as done
                        self.work_queue.task_done()
                except Exception as e:
                    ic(e, os.path.basename(__file__))
        

        This is the run() function of the WorkerThread class, which is a QThread. The WorkerThread class has a required argument work_queue, that is from the queue_worker, which is the queue that will be used.
        The run function constantly checks the if the queue has a new item (the args dict). Then if it finds one, it processes the image.
        self.process_image(self.args) (same file)

            def process_image(self, args):
                isUploadOnline = args["isUploadOnline"]
                self.printer_instance = args["printer_instance"]
                img_path = args["path_to_img"]
        
                # Initiation of Uploading and/or printing tasks
                if isUploadOnline:
                    ic()
                    self.progress.emit("Uploading")
                    self.upload_worker.upload_and_overlay(img_path)
                else:
                    ic()
                    self.progress.emit("Printing")
                    self.print_img(img_path)
        

        Jumping to the upload_and_overlay() function, the function does things:

        1. uploads the image to google drive
        2. creates a qr code using the url generated by the upload
        3. overlays the qr code in the image.
        4. emits a signal containing the path to the new image, so that another class' function can use it to print to a physical printer.

        Now all of that is good, until the second work is added.
        It simply crashes and gives a segmentation fault, which is what I've stated in the last post.
        The program does its thing, until on the part where it updates its progress.
        When no4 (above) gets executed, the function that receives the signal (which lives in the WorkerThread) will emit a signal to the queue_gui (outside of the thread, so its the main thread), stating it's printing. The signal will be received by this function in the queue_gui class:
        queue_gui.py: Queue.update_progress_to_specific_queue_num()

            def update_progress_to_specific_queue_num(self, progress:str):
                current_queue_item = self.find_item_by_value(self.current_work_number)
                current_queue_item_widget = self.list.itemWidget(current_queue_item)
                print(current_queue_item_widget)
                current_queue_item_widget.updateIcons(progress)
        

        This does things:

        1. it gets the current queue_item (a qlistwidgetitem) in a qlistwidget. This does it by using the function find_item_by_value(self.current_work_number). The self.current_work_number comes from the WorkerThread.run() function, this part:
                        # Notify the GUI of the queue number
                        queue_num = self.args["queue_num"]
                        self.queue_number_notifier.emit(queue_num)
                        self.current_args = self.args
        

        I do this since it only updates current_work_number by what it is currently working in the queue. I also use this way because I later implemented restart mechanisms and gets messy quick.

        1. gets the widget associated by the current queue_item, which is a custom made widget.
        2. calls updateIcons() function on the widget, to update the icon status to the user.

        NOW, for the error part, it happens in the function find_item_by_value(), the no1 part above.

        def find_item_by_value(self, value):
                ic()
                for index in range(self.list.count()):
                    ic(self.list.item(index), type(self.list.item(index)), index, self.list.count(), value)
                    list_item = self.list.item(index) 
                    if list_item is None:
                        print(f"Item at index {index} is None")
                        continue
        
                    item_data = list_item.data(Qt.UserRole) # segmentation fault error in here
                    if not item_data or not isinstance(item_data, dict):
                        print(f"Invalid data at index {index}: {item_data}")
                        continue         
        
                    if list_item.data(Qt.UserRole)["queue_num"] == value:
                        return list_item
                return None
        

        This function gets the corresponding qlistwidgetitem from a qlistwidget (self.list), using the value provided. This works because in every qlistwidget item, I assigned a value to them that is the same value in their corresponding args["queue_num"]. The segmentation fault happens when it tries to execute this:
        item_data = list_item.data(Qt.UserRole).

        I don't why this happens. Again, it only happens after i put the second work.

        I'm sorry for my naming inconsistencies

        jsulmJ 1 Reply Last reply
        0
        • P piyeld

          @JonB
          Thank you for replying!
          To answer your question, no.

          For clarity, this program does photobooth stuff---captures images, then puts them into a frame. The action that leads to the error starts in this function.
          print_options.py: PrintOptions.process_to_queue_worker()

          def process_to_queue_worker(self):
                  path = self.frame_presets.getCurrentOverlayedImage()
                  printer_name = self.printer_options.currentText()
                  orientation = self.orientation_options.currentText()
                  isUploadOnline = self.online_uploader.getIsUploadState()
                  name = self.name_form.get_text()
                  current_frame_index = self.frame_presets.getCurrentIndex()
                  current_frame_name = self.frame_presets.getPresets()[current_frame_index]["name"]
          
                  printer_instance = QPrinter(QPrinter.HighResolution)
                  printer_instance.setPrinterName(printer_name)
                  printer_instance.setPageOrientation(getattr(QPageLayout, orientation, None))
                  
                  custom_size = QSizeF(float(self.width_custom.text()), float(self.height_custom.text()))
                  page_size = QPageSize(custom_size, QPageSize.Unit.Inch, "CustomSize")
                  printer_instance.setPageSize(page_size)
          
                  ic()
                  self.queue_worker.addWork({
                      "path_to_img": path, 
                      "printer_instance": printer_instance, 
                      "isUploadOnline": isUploadOnline, 
                      "name": name if name else "No Name", 
                      "size_str": f'{custom_size.width()}x{custom_size.height()}',
                      "frame_name": current_frame_name
                      })
          

          This function's primary work is to collect information from other classes (which are singletons), and then put the in a dictionary that then will be sent to the self.queue_worker.addWork() function
          Moving on to the function's code
          queue_worker.py: QueueWorker.addWork() (singleton)

          def addWork(self, args:dict):
                  args["queue_num"] = self.current_work_number
          
                  data = [f'{args["name"]} - {args["frame_name"]} - {args["size_str"]}', args]
                  self.work_added.emit(data)
                  self.work_queue.put(args)
          
                  self.current_work_number += 1  
          

          This function does things:

          1. adds the key queue_num into the args dict and assigns it the value of self.current_work_number
          2. creates a data variable, which will be used by a custom class, then is emitted by the signal work_added, which will be used by the queue_gui.py: add_to_list()
              def add_to_list(self, item_data: list):
                  list_item = QListWidgetItem()
                  item_widget = QueueItemWidget(item_data[0], item_data[1]["queue_num"])
                  list_item.setData(Qt.UserRole, item_data[1])
                  list_item.setSizeHint(item_widget.sizeHint())
                  self.list.addItem(list_item)
                  self.list.setItemWidget(list_item, item_widget)
          
          1. the args dict is then added to the work_queue, which will later be processed by the WorkerThread
          2. the var self.current_work_number will then be incremented, so that another work will use the variable

          worker.py: WorkerThread

          def run(self):
                  try:
                      while self._is_running:
                          try:
                              ic()
                              # Attempt to get a task from the queue with a timeout
                              self.args = self.work_queue.get(timeout=1)
                          except queue.Empty:
                              continue  # No task available, continue the loop
          
                          # Notify the GUI of the queue number
                          queue_num = self.args["queue_num"]
                          self.queue_number_notifier.emit(queue_num)
                          self.current_args = self.args
          
                          ic()
                          ic(self.args, os.path.basename(__file__))
                          # Process the task
                          self.process_image(self.args)
          
                          # Mark the task as done
                          self.work_queue.task_done()
                  except Exception as e:
                      ic(e, os.path.basename(__file__))
          

          This is the run() function of the WorkerThread class, which is a QThread. The WorkerThread class has a required argument work_queue, that is from the queue_worker, which is the queue that will be used.
          The run function constantly checks the if the queue has a new item (the args dict). Then if it finds one, it processes the image.
          self.process_image(self.args) (same file)

              def process_image(self, args):
                  isUploadOnline = args["isUploadOnline"]
                  self.printer_instance = args["printer_instance"]
                  img_path = args["path_to_img"]
          
                  # Initiation of Uploading and/or printing tasks
                  if isUploadOnline:
                      ic()
                      self.progress.emit("Uploading")
                      self.upload_worker.upload_and_overlay(img_path)
                  else:
                      ic()
                      self.progress.emit("Printing")
                      self.print_img(img_path)
          

          Jumping to the upload_and_overlay() function, the function does things:

          1. uploads the image to google drive
          2. creates a qr code using the url generated by the upload
          3. overlays the qr code in the image.
          4. emits a signal containing the path to the new image, so that another class' function can use it to print to a physical printer.

          Now all of that is good, until the second work is added.
          It simply crashes and gives a segmentation fault, which is what I've stated in the last post.
          The program does its thing, until on the part where it updates its progress.
          When no4 (above) gets executed, the function that receives the signal (which lives in the WorkerThread) will emit a signal to the queue_gui (outside of the thread, so its the main thread), stating it's printing. The signal will be received by this function in the queue_gui class:
          queue_gui.py: Queue.update_progress_to_specific_queue_num()

              def update_progress_to_specific_queue_num(self, progress:str):
                  current_queue_item = self.find_item_by_value(self.current_work_number)
                  current_queue_item_widget = self.list.itemWidget(current_queue_item)
                  print(current_queue_item_widget)
                  current_queue_item_widget.updateIcons(progress)
          

          This does things:

          1. it gets the current queue_item (a qlistwidgetitem) in a qlistwidget. This does it by using the function find_item_by_value(self.current_work_number). The self.current_work_number comes from the WorkerThread.run() function, this part:
                          # Notify the GUI of the queue number
                          queue_num = self.args["queue_num"]
                          self.queue_number_notifier.emit(queue_num)
                          self.current_args = self.args
          

          I do this since it only updates current_work_number by what it is currently working in the queue. I also use this way because I later implemented restart mechanisms and gets messy quick.

          1. gets the widget associated by the current queue_item, which is a custom made widget.
          2. calls updateIcons() function on the widget, to update the icon status to the user.

          NOW, for the error part, it happens in the function find_item_by_value(), the no1 part above.

          def find_item_by_value(self, value):
                  ic()
                  for index in range(self.list.count()):
                      ic(self.list.item(index), type(self.list.item(index)), index, self.list.count(), value)
                      list_item = self.list.item(index) 
                      if list_item is None:
                          print(f"Item at index {index} is None")
                          continue
          
                      item_data = list_item.data(Qt.UserRole) # segmentation fault error in here
                      if not item_data or not isinstance(item_data, dict):
                          print(f"Invalid data at index {index}: {item_data}")
                          continue         
          
                      if list_item.data(Qt.UserRole)["queue_num"] == value:
                          return list_item
                  return None
          

          This function gets the corresponding qlistwidgetitem from a qlistwidget (self.list), using the value provided. This works because in every qlistwidget item, I assigned a value to them that is the same value in their corresponding args["queue_num"]. The segmentation fault happens when it tries to execute this:
          item_data = list_item.data(Qt.UserRole).

          I don't why this happens. Again, it only happens after i put the second work.

          I'm sorry for my naming inconsistencies

          jsulmJ Offline
          jsulmJ Offline
          jsulm
          Lifetime Qt Champion
          wrote on last edited by
          #4

          @piyeld said in segmentation fault (core dumped) when indexing items in a QListWidget to access an item using its data (int) using for loop in PySide6 6.8.1.1:

          find_item_by_value

          From which thread is this called? Because there you're accessing the UI.

          https://forum.qt.io/topic/113070/qt-code-of-conduct

          1 Reply Last reply
          0
          • P Offline
            P Offline
            piyeld
            wrote on last edited by piyeld
            #5

            @jsulm Thanks for replying
            Its on the main thread, called by the variable in current_queue_item var in update_progress_to_specific_queue_num() function. But the update_progress_to_specific_queue_num() is called by the signal that is emitted by the worker thread. Which is safe.

            UPDATE: I solved this problem by changing the data variable in the queue_worker.addWork() function.
            from:

            data = [f'{args["name"]} - {args["frame_name"]} - {args["size_str"]}', args]
            

            to:

            data = [f'{args["name"]} - {args["frame_name"]} - {args["size_str"]}', args["queue_num"]]
            

            I now only sent the queue_num's value, not the whole args dict. It was a dumb idea to send the whole args dict, when some of the information is not even used. Also changed a couple of code in Queue.add_to_list() item_widget var
            from

                        item_widget = QueueItemWidget(item_data[0], item_data[1]["queue_num"])
            

            to

                    item_widget = QueueItemWidget(item_data[0], item_data[1])
            

            and lastly in the function Queue.find_item_by_value()
            from

            if list_item.data(Qt.UserRole)["queue_num"] == value:
                            return list_item
            

            to

            if list_item.data(Qt.UserRole) == value:
                            return list_item
            

            But I still don't know why using the whole args dict threw an error.

            1 Reply Last reply
            0
            • P piyeld has marked this topic as solved on

            • Login

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