Foros Python

Versión completa: Modificar variables desde un hilo(thread) diferente
Actualmente estas viendo una versión simplificada de nuestro contenido. Ver la versión completa con el formato correcto.
Hola amigos, necesito ayuda, estoy aprendiendo a trabajar con visual python, en este momento estoy usando pyQT, pero mi pregunta radica en el uso de hilos.

Mi aplicación recibe datos de un dispositivo todo el tiempo a través del protocolo Modbus, y esto se hace en un hilo diferente al programa principal de la aplicación visual, es decir, el problema está que desde ese hilo no puedo modificar ninguna variable del programa principal o variable global.

Resumiendo, necesito desde el hilo Rx_Thread (), recibir un dato y mostrarlo en un textEdit del programa principal.

  1. from PyQt5 import QtWidgets
  2. from Test_ui import Ui_MainWindow
  3. import sys
  4. from pyModbusTCP.client import ModbusClient
  5. import time, threading
  6.  
  7. c=ModbusClient(host="127.0.0.1", port=502, auto_open=True)
  8. text = "Hola"
  9.  
  10. class Main (QtWidgets.QMainWindow):
  11.      def __init__(self):
  12.          super (Main, self).__init__()
  13.          self.ui = Ui_MainWindow()
  14.          self.ui.setupUi (self)
  15.  
  16.      def Rx_Thread (): #este es el hilo que recibe los datos
  17.          while (True):
  18.              reg = c.read_holding_registers(0, 5)
  19.              time.sleep(1)
  20.          if reg:
  21.              #self.ui.textEdit.setPlainText("%s\n" % text) #esto es lo que quiero modificar
  22.              print(reg)
  23.          else:
  24.              print("not")
  25.  
  26.      _thread = threading.Thread(name='Rx_Thread',target=Rx_Thread, daemon = True)
  27.      _thread.start()
  28.  
  29.  
  30. if __name__ == '__main__':
  31.      app=QtWidgets.QApplication([])
  32.      main_app = Main()
  33.      main_app.show()
  34.      sys.exit(app.exec())
Hola, bienvenido!

Qt tiene una API para hilos similar a la de Python, y un sistema de señales para comunicarse entre diversos hilos. Te dejo un ejemplo de cómo se usa que vas a poder adaptar a tu código:

  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3.  
  4. import time
  5.  
  6. from PyQt5.QtCore import QThread, pyqtSignal
  7. from PyQt5.QtWidgets import QApplication, QMainWindow, QLabel
  8.  
  9.  
  10. class MyThread(QThread):
  11.  
  12. countChanged = pyqtSignal(int)
  13.  
  14. def run(self):
  15. count = 1
  16. while True:
  17. self.countChanged.emit(count)
  18. count += 1
  19. time.sleep(1)
  20.  
  21.  
  22. class MainWindow(QMainWindow):
  23.  
  24. def __init__(self):
  25. super().__init__()
  26. self.setWindowTitle("Ejemplo de QThread")
  27. self.resize(400, 300)
  28. self.label = QLabel("Cuenta: 0", self)
  29. self.label.setGeometry(20, 20, 200, 25)
  30.  
  31. self.thread = MyThread()
  32. self.thread.countChanged.connect(self.countChanged)
  33. self.thread.start()
  34.  
  35. def countChanged(self, count):
  36. self.label.setText(f"Cuenta: {count}")
  37.  
  38.  
  39. if __name__ == "__main__":
  40. app = QApplication([])
  41. window = MainWindow()
  42. window.show()
  43. app.exec_()


Este programa inicializa un hilo que cada un segundo aumenta un contador y actualiza el texto de una etiqueta (QLabel). El contador se actualiza en el hilo (clase MyThread), pero emite una señal (countChanged) a la cual el hilo principal (clase MainWindow) conecta la función MainWindow.countChanged(), que es llamada cada vez que se recibe esa señal, y ahí se hace la actualización del texto de la etiqueta. En términos más simples: el hilo MyThread emite la señal countChanged que es recibida en el hilo principal MainWindow.

En el ejemplo la señal (MyThread.countChanged) y la función que recibe esa señal (MainWindow.countChanged) tienen el mismo nombre, pero eso no es para nada necesario. Le podés dar el nombre que quieras tanto a tu señal (en tu caso sería algo así como "registerChanged" o no sé qué dato estás leyendo) como a tu función.

Saludos
Muchas Gracias Francisco me fue de mucha ayuda y ya me funciona a la perfección. Saludos