El subprocess que imprime en el seudoterminal no está utilizando el tamaño completo del terminal.
Tengo el siguiente programa que envuelve top
en un seudoterminal y lo muestra de vuelta en el terminal real.
import os
import pty
import subprocess
import sys
import time
import select
stdout_master_fd, stdout_slave_fd = pty.openpty()
stderr_master_fd, stderr_slave_fd = pty.openpty()
p = subprocess.Popen(
"top",
shell=True,
stdout=stdout_slave_fd,
stderr=stderr_slave_fd,
close_fds=True
)
stdout_parts = []
while p.poll() is None:
rlist, _, _ = select.select([stdout_master_fd, stderr_master_fd], [], [])
for f in rlist:
output = os.read(f, 1000) # Esto se usa porque no bloquea
sys.stdout.write(output.decode("utf-8"))
sys.stdout.flush()
time.sleep(0.01)
Esto funciona bien y las secuencias de control se manejan como se espera. Sin embargo, el subproceso no está utilizando las dimensiones completas del terminal real.
Para comparar, ejecutando el programa anterior:
Y ejecutando top
directamente:
No encontré ninguna API de la biblioteca pty
que sugiera que se pueden proporcionar dimensiones.
Las dimensiones que obtengo en la práctica para el seudoterminal son una altura de 24 líneas y un ancho de 80 columnas, estoy asumiendo que podrían estar codificadas en algún lugar.
davy.ai
Solución:
La librería
pty
no tiene una API directa para establecer las dimensiones del pseudo terminal. Sin embargo, podemos usar el módulofcntl
para lograr lo mismo.Aquí está una versión actualizada del programa que establece las dimensiones del pseudo terminal para que coincida con las dimensiones del terminal real:
Aquí, estamos utilizando el método
fcntl.ioctl()
para establecer las dimensiones del pseudo terminal. Primero usamosstruct.unpack()
para obtener la altura y el ancho del terminal real, y luego usamosfcntl.ioctl()
para establecer estas dimensiones en el pseudo terminal usandotermios.TIOCSWINSZ
.Con estos cambios, el subprocess ahora utiliza las dimensiones completas del terminal real: