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 conself.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 argumentopreexec_fn
desubprocess.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 afile.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