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.

Reinicie una función de Python en un script después de n minutos.

Tengo un script que usa una biblioteca de eventos enviados por el servidor para conectarse con un servidor que me envía eventos regularmente. El problema es que el flujo se congela después de mucho tiempo y tengo que reiniciar manualmente el script y esto no es sostenible. La estructura del código actual se ve así:

def listen(self):
        print("escuchando eventos.....")
        try:
            url = settings.EVENT_URL + "/v1/events"
            auth_key = settings.KEY

        headers = {
            "Authorization": "Basic " + auth_key,
            "Accept": "text/event-stream",
        }

        response = self.with_urllib3(url, headers)
        client = sseclient.SSEClient(response)

        for event in client.events():
            # el script se congela aquí.
            logger.info(event.data)

            process(event.data)

He intentado hacer algo como esto:

def start(self):
    def wait():
        time.sleep(10 * 60)

background = threading.Thread(name='fondo', target=self.listen)
background.daemon = True
background.start()
wait()

try:
    self.start()
except:
    self.start()
finally:
    self.start()

Pero no sé si esto funcionará principalmente porque un hilo demonio seguirá ejecutándose en segundo plano, lo que significa que tendré copias de la tarea en ejecución después de un tiempo.

Lo que necesito es una mejor manera de llamar a una función y después de algún tiempo transcurrido volver de la función y volver a llamarla inmediatamente. Gracias por cualquier ayuda.

Tags:  ,

Answer

  1. Avatar for davy.ai

    Parece ser que el problema está relacionado con el script que se congela después de un largo tiempo debido al flujo de eventos enviados por el servidor. Un enfoque para evitarlo es crear un bucle dentro de la función listen que verifica periódicamente si el flujo de eventos sigue activo.

    Aquí hay un ejemplo de implementación:

    import time
    
    class EventListener:
        def __init__(self):
            self.is_running = False
    
        def start(self):
            self.is_running = True
            while self.is_running:
                try:
                    self.listen()
                except Exception as e:
                    print(e)
                    # esperar algún tiempo antes de reintentar
                    time.sleep(60)
    
        def stop(self):
            self.is_running = False
    
        def listen(self):
            print("escuchando eventos...")
            url = settings.EVENT_URL + "/v1/events"
            auth_key = settings.KEY
    
            headers = {
                "Authorization": "Basic " + auth_key,
                "Accept": "text/event-stream",
            }
    
            response = self.with_urllib3(url, headers)
            client = sseclient.SSEClient(response)
    
            for event in client.events():
                if not self.is_running:
                    break
                # continuar procesando eventos
                print(event.data)
                process(event.data)
                # verificar si la conexión sigue activa
                if client.requests:
                    # esperar algún tiempo antes de verificar de nuevo
                    time.sleep(10)
                else:
                    # reconectar al servidor
                    break
    

    En esta implementación, el método start inicia un bucle infinito que llama a la función listen. La función listen crea una nueva instancia de SSEClient en cada llamada y recorre los eventos. También verifica periódicamente si la conexión sigue activa mirando el atributo client.requests. Si se pierde la conexión, el bucle se interrumpe y la función listen devuelve, lo que causará que el método start vuelva a llamar a la función listen.

    Para detener el bucle, puede llamar al método stop de la instancia EventListener. Esto establecerá el indicador is_running en False y romperá el bucle infinito.

    event_listener = EventListener()
    event_listener.start()
    
    # ... después de algún tiempo
    event_listener.stop()
    

    Tenga en cuenta que esta implementación utiliza una llamada time.sleep para esperar algún tiempo antes de verificar la conexión nuevamente. Es posible que deba ajustar la duración del intervalo de espera según su caso de uso específico.

Comments are closed.