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.

Cómo lanzar, monitorear y terminar un proceso en Python.

Necesito poder iniciar un proceso de larga duración en Python. Mientras el proceso está en ejecución, necesito redirigir su salida a mi aplicación de Python para mostrarla en la interfaz de usuario. La interfaz de usuario también debe poder finalizar el proceso.

He investigado mucho, pero no he encontrado una forma de hacer las tres cosas.

subprocess.popen() me permite iniciar un proceso y finalizarlo si es necesario. Pero no me permite ver su salida hasta que el proceso haya terminado. Y el proceso que estoy supervisando nunca termina por sí mismo.

os.popen() me permite iniciar un proceso y supervisar su salida mientras se está ejecutando. Pero no conozco una forma de finalizarlo. Normalmente estoy en medio de una llamada a readline().

Cuando uso os.popen(), ¿hay alguna forma de saber si hay datos en el búfer antes de llamar a read() o readline? Por ejemplo…

salida = os.popen(comando)
while True:
# ¿Hay alguna forma de verificar si hay datos disponibles
# antes de hacer esta llamada bloqueante? ¿O hay alguna forma de hacer una
# lectura no bloqueante?
linea = salida.readline()
print(linea)

Gracias de antemano.

Tags:  , , ,

Answer

  1. Avatar for davy.ai

    Para lanzar un proceso de larga duración en Python y redirigir su salida a la interfaz de usuario (UI) al mismo tiempo que permite a la UI finalizar el proceso, se puede utilizar el módulo subprocess en conjunto con multithreading.

    Aquí hay un ejemplo de código para lograr esto:

    import subprocess
    import threading
    
    def run_process(cmd, output_callback):
        process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        while True:
            output = process.stdout.readline()
            if output == '' and process.poll() is not None:
                break
            if output:
                # Llama a la función output_callback para mostrar la salida en la UI
                output_callback(output)
        if process.poll() != 0:
            output_callback(process.stderr.read())
    
    def start_process(cmd, output_callback):
        process_thread = threading.Thread(target=run_process, args=(cmd, output_callback))
        process_thread.start()
        return process_thread
    
    def stop_process(process_thread):
        process_thread._is_stopped = True
        process_thread.join(timeout=5)
        if process_thread.is_alive():
            process_thread.terminate()
    
    # Ejemplo de uso
    def handle_output(output):
        print(output.strip().decode("utf-8"))
    
    process_thread = start_process(["long_running_command"], handle_output)
    # ... hacer otras cosas ...
    stop_process(process_thread)
    

    La función start_process crea un nuevo hilo para ejecutar el comando proporcionado, pasando una función de devolución de llamada (output_callback) para manejar la salida. La función run_process ejecuta el comando utilizando el método subprocess.Popen y lee la salida línea por línea. Luego, cada línea se pasa a la función output_callback.

    La función stop_process establece una bandera en el hilo para indicar que debe dejar de procesar, espera hasta 5 segundos para que el hilo finalice y luego lo termina forzadamente si aún está en ejecución.

    Utilizando este enfoque, la UI puede iniciar el proceso, mostrar continuamente su salida mientras se ejecuta y tener la capacidad de detenerlo en cualquier momento. La función output_callback se puede utilizar para mostrar la salida en la UI en tiempo real.

Comments are closed.