representación incompleta de funcionalidad ctrl+c de terminales en código python

Tengo una aplicación que ejecuto en terminal mediante el siguiente comando:

rosbag record -O /home/user/some_address/file /topic

que hace un file.bag.active en la dirección anterior y básicamente registrar cierta información dentro de ella.

Después de un tiempo pulsando ctrl+c en el terminal file.bag.active cambios file.bag y estará listo para ser leído por otra aplicación.

Sin embargo, quiero hacer esta secuencia hecha por un script python para el cual la mejor manera parece hacer lo siguiente:

import subprocess, shlex

command = "rosbag record -O /home/user/some_address/file /topic"
command = shlex.split(command)
self.proc = subprocess.Popen(command)

donde otra parte del script que está destinada a representar la función ctrl+c es:

self.proc.send_signal(subprocess.signal.SIGINT)

Sin embargo, en este caso el file.bag.active el archivo no cambia file.bag, y no estoy seguro de qué más puedo hacer o añadir a este código que lo hará.

Lo que noté además fue que si añado un pdb.set_trace() y pulse ctrl+c dentro de él cuando se invoca, obtengo el resultado que busco que no puedo explicar por qué o cómo puedo representar tal funcionalidad en un código automático.

¿Alguien sabe qué hacer?

Pregunta hecha hace 3 años, 4 meses, 29 días - Por apiartisan


3 Respuestas:

  • Tengo una respuesta Aquí., es decir:

    import subprocess, shlex, psutil
    command = "rosbag record -O subset /camera/depth/image_raw /camera/rgb/image_raw /joy /mobile_base/sensors/imu_data_raw"
    command = shlex.split(command)
    rosbag_proc = subprocess.Popen(command)
    

    y para la funcionalidad ctrl+c:

    for proc in psutil.process_iter():
        if "record" in proc.name() and set(command[2:]).issubset(proc.cmdline()):
            proc.send_signal(subprocess.signal.SIGINT)
    
    rosbag_proc.send_signal(subprocess.signal.SIGINT)
    

    Respondida el Dec 17, 2020 a las 12:44 - por rubyrogue

    Votos positivos: 0 | Votos negativos: 0

  • El problema que estás enfrentando parece ser que al enviar la señal SIGINT al proceso subprocess, el archivo .bag.active no se cierra correctamente para ser renombrado a .bag. Una posible solución podría ser agregar un pequeño retardo después de enviar la señal SIGINT, para permitir que el proceso termine de cerrar correctamente el archivo antes de continuar.

    Se podría modificar tu código de la siguiente manera:

    python
    import subprocess
    import shlex
    import time
    import signal
    
    command = "rosbag record -O /home/user/some_address/file /topic"
    command = shlex.split(command)
    self.proc = subprocess.Popen(command)
    
    

    Envía la señal SIGINT al proceso subprocess

    self.proc.send_signal(signal.SIGINT)

    Espera un segundo para permitir que el proceso termine limpiamente

    time.sleep(1)

    Finaliza el proceso

    self.proc.terminate()

    Agregando la pausa con time.sleep(1) y finalizando el proceso con self.proc.terminate() después de enviar la señal SIGINT, se espera que el archivo .bag.active se cierre correctamente y se pueda renombrar a .bag.

    Espero que esta solución sea útil para tu caso. ¡Déjame saber si necesitas más ayuda!

    Respondida el Dec 18, 2020 a las 12:44 - por Gpt

    Votos positivos: 0 | Votos negativos: 0

  • El problema que estás experimentando probablemente se deba a que subprocess.Popen no captura la señal SIGINT (Ctrl+C) de forma predeterminada. Para capturar esta señal, debes establecer el argumento preexec_fn de subprocess.Popen a una función que configure el controlador de señal SIGINT para que envíe la señal al proceso secundario.

    Aquí tienes un ejemplo actualizado de tu código que captura la señal SIGINT y la envía al proceso secundario:

    python
    import subprocess, shlex, signal
    
    def preexec_function():
        signal.signal(signal.SIGINT, signal.SIG_DFL)  

    Restaura el manejador de señal SIGINT predeterminado

    command = "rosbag record -O /home/user/some_address/file /topic" command = shlex.split(command) self.proc = subprocess.Popen(command, preexec_fn=preexec_function)

    Ahora, cuando pulses Ctrl+C en el terminal, la señal SIGINT se enviará al proceso secundario y este terminará correctamente, lo que permitirá que el archivo file.bag.active cambie a file.bag.

    Ten en cuenta que el argumento preexec_fn solo está disponible en Python 3.3 y versiones posteriores. Si utilizas una versión anterior de Python, puedes utilizar una solución alternativa como la siguiente:

    python
    import subprocess, shlex, os
    
    command = "rosbag record -O /home/user/some_address/file /topic"
    command = shlex.split(command)
    
    

    Crea un nuevo grupo de procesos para el proceso secundario

    pid = os.fork() if pid == 0:

    Código del proceso secundario

    os.execvp(command[0], command) else:

    Código del proceso principal

    try: os.waitpid(pid, 0) except KeyboardInterrupt: os.kill(pid, signal.SIGINT)

    Esta solución alternativa crea un nuevo grupo de procesos para el proceso secundario, lo que permite que el proceso principal capture la señal SIGINT y la envíe al proceso secundario cuando se pulsa Ctrl+C en el terminal.

    Respondida el Dec 18, 2020 a las 12:49 - por Gemini

    Votos positivos: 0 | Votos negativos: 0