Cómo obtener el ancho de la ventana de la consola Linux en Python
¿Hay alguna forma en python de determinar programáticamente el ancho de la consola? Me refiero al número de caracteres que cabe en una línea sin envolver, no al ancho de píxel de la ventana.
Editar
Buscando una solución que funcione en Linux
14 answers
import os
rows, columns = os.popen('stty size', 'r').read().split()
Utiliza el comando 'stty size' que según un hilo en la lista de correo de python es razonablemente universal en linux. Abre el comando 'stty size' como un archivo, 'lee' de él, y usa una simple división de cadena para separar las coordenadas.
A diferencia del sistema operativo.environ ["COLUMNS"] valor (al que no puedo acceder a pesar de usar bash como mi shell estándar) los datos también estarán actualizados, mientras que creo que el sistema operativo.environ ["COLUMNS"] value would only be valid for the time of el lanzamiento del intérprete de python (supongamos que el usuario redimensionó la ventana desde entonces).
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-06-03 10:06:54
No estoy seguro de por qué está en el módulo shutil
, pero aterrizó allí en Python 3.3, Consultando el tamaño del terminal de salida :
>>> import shutil
>>> shutil.get_terminal_size((80, 20)) # pass fallback
os.terminal_size(columns=87, lines=23) # returns a named-tuple
Una implementación de bajo nivel está en el módulo de so.
Un backport ahora está disponible para Python 3.2 y versiones posteriores:
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-03-30 17:45:29
Use
import console
(width, height) = console.getTerminalSize()
print "Your terminal's width is: %d" % width
EDIT: oh, lo siento. Eso no es una lib estándar de python, aquí está la fuente de console.py (No se de donde es).
El módulo parece funcionar así: Comprueba si termcap
está disponible, cuando sí. Usa eso; si no comprueba si el terminal soporta una llamada especial ioctl
y eso no funciona, también comprueba las variables de entorno que algunos shells exportan para eso.
Esto probablemente funcionará solo en UNIX.
def getTerminalSize():
import os
env = os.environ
def ioctl_GWINSZ(fd):
try:
import fcntl, termios, struct, os
cr = struct.unpack('hh', fcntl.ioctl(fd, termios.TIOCGWINSZ,
'1234'))
except:
return
return cr
cr = ioctl_GWINSZ(0) or ioctl_GWINSZ(1) or ioctl_GWINSZ(2)
if not cr:
try:
fd = os.open(os.ctermid(), os.O_RDONLY)
cr = ioctl_GWINSZ(fd)
os.close(fd)
except:
pass
if not cr:
cr = (env.get('LINES', 25), env.get('COLUMNS', 80))
### Use get(key[, default]) instead of a try/catch
#try:
# cr = (env['LINES'], env['COLUMNS'])
#except:
# cr = (25, 80)
return int(cr[1]), int(cr[0])
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-11-14 19:38:02
El código anterior no devolvió el resultado correcto en mi linux porque winsize-struct tiene 4 cortos sin firmar, no 2 cortos firmados:
def terminal_size():
import fcntl, termios, struct
h, w, hp, wp = struct.unpack('HHHH',
fcntl.ioctl(0, termios.TIOCGWINSZ,
struct.pack('HHHH', 0, 0, 0, 0)))
return w, h
Hp y hp deben contener ancho y alto de píxeles, pero no lo hacen.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-06-09 22:36:38
Busqué alrededor y encontré una solución para windows en :
Http://code.activestate.com/recipes/440694-determine-size-of-console-window-on-windows/
Y una solución para linux aquí.
Así que aquí hay una versión que funciona tanto en linux, os x y windows / cygwin:
""" getTerminalSize()
- get width and height of console
- works on linux,os x,windows,cygwin(windows)
"""
__all__=['getTerminalSize']
def getTerminalSize():
import platform
current_os = platform.system()
tuple_xy=None
if current_os == 'Windows':
tuple_xy = _getTerminalSize_windows()
if tuple_xy is None:
tuple_xy = _getTerminalSize_tput()
# needed for window's python in cygwin's xterm!
if current_os == 'Linux' or current_os == 'Darwin' or current_os.startswith('CYGWIN'):
tuple_xy = _getTerminalSize_linux()
if tuple_xy is None:
print "default"
tuple_xy = (80, 25) # default value
return tuple_xy
def _getTerminalSize_windows():
res=None
try:
from ctypes import windll, create_string_buffer
# stdin handle is -10
# stdout handle is -11
# stderr handle is -12
h = windll.kernel32.GetStdHandle(-12)
csbi = create_string_buffer(22)
res = windll.kernel32.GetConsoleScreenBufferInfo(h, csbi)
except:
return None
if res:
import struct
(bufx, bufy, curx, cury, wattr,
left, top, right, bottom, maxx, maxy) = struct.unpack("hhhhHhhhhhh", csbi.raw)
sizex = right - left + 1
sizey = bottom - top + 1
return sizex, sizey
else:
return None
def _getTerminalSize_tput():
# get terminal width
# src: http://stackoverflow.com/questions/263890/how-do-i-find-the-width-height-of-a-terminal-window
try:
import subprocess
proc=subprocess.Popen(["tput", "cols"],stdin=subprocess.PIPE,stdout=subprocess.PIPE)
output=proc.communicate(input=None)
cols=int(output[0])
proc=subprocess.Popen(["tput", "lines"],stdin=subprocess.PIPE,stdout=subprocess.PIPE)
output=proc.communicate(input=None)
rows=int(output[0])
return (cols,rows)
except:
return None
def _getTerminalSize_linux():
def ioctl_GWINSZ(fd):
try:
import fcntl, termios, struct, os
cr = struct.unpack('hh', fcntl.ioctl(fd, termios.TIOCGWINSZ,'1234'))
except:
return None
return cr
cr = ioctl_GWINSZ(0) or ioctl_GWINSZ(1) or ioctl_GWINSZ(2)
if not cr:
try:
fd = os.open(os.ctermid(), os.O_RDONLY)
cr = ioctl_GWINSZ(fd)
os.close(fd)
except:
pass
if not cr:
try:
cr = (env['LINES'], env['COLUMNS'])
except:
return None
return int(cr[1]), int(cr[0])
if __name__ == "__main__":
sizex,sizey=getTerminalSize()
print 'width =',sizex,'height =',sizey
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-07-05 09:22:23
A partir de Python 3.3 es sencillo: https://docs.python.org/3/library/os.html#querying-the-size-of-a-terminal
>>> import os
>>> ts = os.get_terminal_size()
>>> ts.lines
24
>>> ts.columns
80
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-04-27 23:24:31
Parece que hay algunos problemas con ese código, Johannes: {[14]]}
-
getTerminalSize
necesitaimport os
- ¿qué es
env
? pareceos.environ
.
También, ¿por qué cambiar lines
y cols
antes de regresar? Si TIOCGWINSZ
y stty
ambos dicen lines
entonces cols
, yo digo que lo dejes así. Esto me confundió por un buen 10 minutos antes de que me di cuenta de la inconsistencia.
Sridhar, no obtuve ese error cuando canalé la salida. Estoy bastante seguro de que está siendo atrapado correctamente en el inténtalo, excepto.
Pascal, "HHHH"
no funciona en mi máquina, pero "hh"
hace. Tuve problemas para encontrar documentación para esa función. Parece que depende de la plataforma.
Chochem, incorporated.
Aquí está mi versión:
def getTerminalSize():
"""
returns (lines:int, cols:int)
"""
import os, struct
def ioctl_GWINSZ(fd):
import fcntl, termios
return struct.unpack("hh", fcntl.ioctl(fd, termios.TIOCGWINSZ, "1234"))
# try stdin, stdout, stderr
for fd in (0, 1, 2):
try:
return ioctl_GWINSZ(fd)
except:
pass
# try os.ctermid()
try:
fd = os.open(os.ctermid(), os.O_RDONLY)
try:
return ioctl_GWINSZ(fd)
finally:
os.close(fd)
except:
pass
# try `stty size`
try:
return tuple(int(x) for x in os.popen("stty size", "r").read().split())
except:
pass
# try environment variables
try:
return tuple(int(os.getenv(var)) for var in ("LINES", "COLUMNS"))
except:
pass
# i give up. return default.
return (25, 80)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-06-16 07:23:51
Muchas de las implementaciones de Python 2 aquí fallarán si no hay un terminal de control cuando llame a este script. Puede comprobar sys.stdout.isatty () para determinar si esto es de hecho una terminal, pero eso excluirá un montón de casos, así que creo que la forma más pitónica de averiguar el tamaño de la terminal es usar el paquete integrado curses.
import curses
w = curses.initscr()
height, width = w.getmaxyx()
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-05-31 22:26:04
Es:
import os
columns, rows = os.get_terminal_size(0)
# or
import shutil
columns, rows = shutil.get_terminal_size()
La función shutil
es solo una envoltura alrededor de os
que detecta algunos errores y configura una reserva, sin embargo, tiene una gran advertencia: ¡se rompe al canalizar!, lo cual es bastante importante.
Para obtener el tamaño del terminal cuando se utiliza la tubería os.get_terminal_size(0)
en su lugar.
Primer argumento 0
es un argumento que indica que el descriptor de archivo stdin debe ser utilizado en lugar de la salida estándar predeterminada. Queremos usar stdin porque stdout se separa cuando está siendo canalizado que plantea en este caso plantea un error..
He intentado averiguar cuándo tendría sentido usar stdout en lugar del argumento stdin y no tengo idea de por qué es un valor predeterminado aquí.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-05-03 04:51:39
La respuesta de@reannual funciona bien, pero hay un problema con ella: os.popen
ahora está en desuso . El módulo subprocess
debe usarse en su lugar, por lo que aquí hay una versión del código de @reannual que usa subprocess
y responde directamente a la pregunta (dando el ancho de la columna directamente como int
:
import subprocess
columns = int(subprocess.check_output(['stty', 'size']).split()[1])
Probado en OS X 10.9
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-07-22 18:30:16
Estaba intentando la solución desde aquí que llama a stty size
:
columns = int(subprocess.check_output(['stty', 'size']).split()[1])
Sin embargo, esto falló para mí porque estaba trabajando en un script que espera la entrada redirigida en stdin, y stty
se quejaría de que "stdin no es una terminal" en ese caso.
Pude hacer que funcionara así:
with open('/dev/tty') as tty:
height, width = subprocess.check_output(['stty', 'size'], stdin=tty).split()
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-09-08 18:36:32
Intenta "bendiciones"
Estaba buscando lo mismo. Es muy fácil de usar y ofrece herramientas para colorear, estilo y posicionamiento en el terminal. Lo que necesitas es tan fácil como:
from blessings import Terminal
t = Terminal()
w = t.width
h = t.height
Funciona como un encanto en Linux. (No estoy seguro sobre MacOSX y Windows)
Descarga y documentación aquí
O puede instalarlo con pip:
pip install blessings
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-12-23 12:00:41
Si está utilizando Python 3.3 o superior, le recomendaría el incorporado get_terminal_size()
como ya se recomienda. Sin embargo, si está atascado con una versión anterior y desea una forma simple y multiplataforma de hacer esto, podría usar asciimatics. Este paquete soporta versiones de Python de vuelta a la 2.7 y usa opciones similares a las sugeridas anteriormente para obtener el tamaño actual de terminal / consola.
Simplemente construya su clase Screen
y use la propiedad dimensions
para obtener la altura y el ancho. Esto tiene se ha demostrado que funciona en Linux, OSX y Windows.
Oh - y la divulgación completa aquí: Yo soy el autor, así que por favor no dude en abrir un nuevo número si tiene algún problema para conseguir que esto funcione.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-12-24 09:54:50
Aquí hay una versión que debería ser compatible con Linux y Solaris. Basado en los mensajes y comentarios de madchine . Requiere el módulo subprocess.
def termsize(): import shlex, subprocess, re output = subprocess.check_output(shlex.split('/bin/stty -a')) m = re.search('rows\D+(?P\d+); columns\D+(?P\d+);', output) if m: return m.group('rows'), m.group('columns') raise OSError('Bad response: %s' % (output))
>>> termsize() ('40', '100')
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 11:55:19