es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Llamando a una función de hilo principal desde otro hilo a través de valor en lugar de referencia en Python.

Así que he estado pensando en esto durante un par de días y no puedo resolverlo, he buscado alrededor pero no pude encontrar la respuesta que estaba buscando, por lo que cualquier ayuda sería muy apreciada.

Básicamente lo que estoy tratando de hacer es llamar a un método en un grupo de objetos en mi hilo principal desde un hilo separado, solo una vez después de 2 segundos y luego el hilo puede salir, solo estoy usando threading como una forma de crear una pausa no bloqueante de 2 segundos (si hay otras formas de lograr esto, por favor hágamelo saber).

Entonces tengo un gráfico/pyqtplot que se actualiza desde una transmisión de websocket y el gui solo puede actualizarse desde el hilo que lo inició (el principal).
Lo que sucede es que abro una transmisión de websocket, lleno un búfer durante aproximadamente 2 segundos, hago una solicitud REST, aplico las actualizaciones del búfer a los datos de la solicitud REST y luego actualizo los datos/gráficos a medida que llegan nuevos mensajes. Ahora el problema es que no puedo crear una pausa no bloqueante de 2 segundos en el hilo principal sin crear un hilo hijo. Si creo un hilo hijo y le paso el objeto que contiene el diccionario que quiero actualizar después de 2 segundos, obtengo problemas con respecto a la actualización del gráfico desde un hilo diferente. Entonces, lo que creo que sucede es que cuando se crea ese nuevo hilo generado, la referencia al objeto que quiero actualizar es en realidad el objeto en sí mismo, o los datos (diccionario) que contienen los datos de actualización están ahora en un hilo diferente al gui y esto causa problemas.

Abrir websocket -> comenzar a llenar el búfer -> esperar 2 segundos -> solicitud REST -> aplicar actualizaciones del búfer a los datos REST -> actualizar datos a medida que llegan nuevas actualizaciones/mensajes de websocket.

Desafortunadamente, la transmisión de websocket y el gui solo se inician cuando ejecuta pg.exec() y no puede dividirlas para iniciarlas individualmente, las crea y luego las inicia juntas (o al menos no he encontrado una forma de iniciarlas individualmente, alternativamente también intenté usar una biblioteca separada para manejar websockets, sin embargo, esto requiere iniciar un hilo para los mensajes entrantes también).

Este es el ejemplo mínimo reproducible, lo siento es bastante largo pero no pude dividirlo más sin eliminar la funcionalidad requerida y preservar el contexto:

Tags:  , , , ,

Answer

  1. Avatar for davy.ai

    Para llamar a un método en un grupo de objetos en el hilo principal desde un hilo separado, puedes hacer uso de la clase QTimer de PyQt. Aquí te mostramos cómo puedes implementarlo en tu código:

    1. Primero, debes importar la clase QTimer de PyQt:
      from PyQt5.QtCore import QTimer
      
    2. Luego, puedes crear un método, por ejemplo actualizar_datos, que llame al método que quieras ejecutar después de 2 segundos:
      def actualizar_datos(self):
         self.getOrderBookSnapshot()
      
    3. Después, en tu método delay, puedes crear un objeto QTimer, conectarlo al método actualizar_datos y comenzarlo con un tiempo de espera de 2 segundos:
      def delay(miObj):
         temporizador = QTimer()
         temporizador.timeout.connect(miObj.actualizar_datos)
         temporizador.start(2000)
      
    4. Finalmente, en tu función main, puedes eliminar el hilo getorderbook y llamar al método delay directamente:
      def main():
         pg.mkQApp()
         objRef = coin()
         websock = QtWebSockets.QWebSocket()
         websock.connected.connect(lambda : print('connected'))
         websock.disconnected.connect(lambda : print('disconnected'))
         websock.error.connect(lambda e : print('error', e))
         websock.textMessageReceived.connect(functools.partial(on_text_message, refObj=objRef))
         url = QtCore.QUrl("wss://stream.binance.com:9443/ws/btcusdt@depth@1000ms")
         websock.open(url)
         delay(objRef)
         pg.exec()
      

    Con estos cambios, el método actualizar_datos se llamará cada 2 segundos desde el hilo principal, sin necesidad de un hilo separado. Esto debería solucionar los problemas que tienes al actualizar la trama desde un hilo diferente.

Comments are closed.