Pregunta

¿Hay alguna manera en Python para determinar mediante programación el ancho de la consola? Me refiero a la cantidad de caracteres que cabe en una sola línea y sin envolver, no el ancho de píxel de la ventana.

Editar

Búsqueda de una solución que funciona en Linux

¿Fue útil?

Solución

import os
rows, columns = os.popen('stty size', 'r').read().split()

utiliza el comando 'tamaño stty' que según un hilo en la lista de correo pitón es razonablemente universal sobre Linux. Se abre el comando 'tamaño stty' como un archivo, 'lee' de ella, y utiliza una cadena simple dividido para separar las coordenadas.

A diferencia de los os.environ [ "columnas"] valor (que no pueden acceder a pesar de utilizar bash como mi concha estándar) los datos también será de hasta al día mientras que creo que el os.environ [" COLUMNAS "] valor sólo sería válida para el momento de la puesta en marcha del intérprete de Python (supongamos que el usuario cambia el tamaño de la ventana desde entonces).

Otros consejos

No está seguro de por qué está en la shutil módulo, pero no aterrizó en Python 3.3, Consultar 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 se encuentra en el módulo os.

A backport está ahora disponible para Python 3.2 y por debajo de:

uso

import console
(width, height) = console.getTerminalSize()

print "Your terminal's width is: %d" % width

Editar : Oh, lo siento. Eso no es una pitón uno lib estándar, aquí está la fuente de console.py (no sé de dónde viene).

El módulo parece que funciona así: Se comprueba si está disponible termcap, cuando sí. Utiliza eso; si no se comprueba si el terminal soporta un llamado especial ioctl y que no funciona, también, comprueba las variables de entorno de algunas conchas exportan para eso. Esto probablemente funcionará 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])

Código anterior no arrojó resultado correcto en mi Linux porque winsize-estructura tiene 4 unsignedshorts, no pantalones cortos firmados 2:

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 de píxel y la altura, pero no lo hacen.

Busqué y encontré una solución para las ventanas en:

http://code.activestate.com/recipes/ 440694-determinar el tamaño de la consola-window-on-windows /

y una solución para Linux aquí.

Así que aquí es 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

A partir de Python 3.3 es sencillo: https://docs.python.org/3/library/ os.html # consulta-el-size-of-a-terminal

>>> import os
>>> ts = os.get_terminal_size()
>>> ts.lines
24
>>> ts.columns
80

Es bien:

import os
columns, rows = os.get_terminal_size(0)
# or
import shutil
columns, rows = shutil.get_terminal_size()

La función shutil es sólo un envoltorio alrededor de una os que las capturas de algunos errores y estableció un repliegue, sin embargo, tiene una gran advertencia - se rompe cuando la tubería , que es un muy gran negocio!.
Tener conseguir tamaño terminal cuando tuberías Empleo os.get_terminal_size(0) lugar.

En primer lugar 0 argumento es un argumento que indica que el archivo descriptor de la entrada estándar se debe utilizar en lugar de la salida estándar por defecto. Queremos utilizar la entrada estándar debido a la salida estándar se desprende cuando está siendo canalizado lo que plantea en este caso genera un error ..
He tratado de averiguar ¿Cuándo tiene sentido utilizar la salida estándar en lugar de la entrada estándar argumento y no tienen idea de por qué un defecto aquí.

Parece que hay algunos problemas con ese código, Johannes:

  • getTerminalSize necesita import os
  • ¿qué es env? parece os.environ.

Además, ¿por interruptor lines y cols antes de regresar? Si TIOCGWINSZ y stty ambos dicen lines continuación cols, digo dejar de esa manera. Esto me confundió durante más de 10 minutos antes de notar la falta de coherencia.

Sridhar, no tuve ese error cuando me toqué salida. Estoy bastante seguro de que está siendo capturado adecuadamente en el intento, excepto.

Pascal, "HHHH" no funciona en mi máquina, pero "hh" hace. Tuve problemas para encontrar la documentación para esa función. Parece que es dependiente de la plataforma.

Chochem, Incorporated.

Esta es 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)

Muchos de los Python 2 implementaciones aquí se producirá un error si no hay un terminal de control cuando se llama a este script. Puede comprobar sys.stdout.isatty () para determinar si este es de hecho un terminal, pero que excluya un montón de casos, por lo que creo que la forma más Pythonic de averiguar el tamaño del terminal es utilizar el paquete maldiciones orden interna.

import curses
w = curses.initscr()
height, width = w.getmaxyx()

Yo estaba tratando la solución de aquí que llama a stty size:

columns = int(subprocess.check_output(['stty', 'size']).split()[1])

Sin embargo, este error para mí porque yo estaba trabajando en un guión que espera redirigido entrada de la entrada estándar, y stty se quejaba de que "la entrada estándar no es un terminal" en ese caso.

yo era capaz de hacer que funcione de esta manera:

with open('/dev/tty') as tty:
    height, width = subprocess.check_output(['stty', 'size'], stdin=tty).split()
respuesta

@ de reannual funciona bien, pero hay un problema con él: os.popen ahora está en desuso . El módulo subprocess se debe utilizar en su lugar, así que aquí está una versión del código de @ reannual que utiliza subprocess y directamente responde a la pregunta (dando el ancho de columna directamente como un int:

import subprocess

columns = int(subprocess.check_output(['stty', 'size']).split()[1])

Probado en OS X 10.9

Trate "bendiciones"

Yo estaba buscando la misma cosa. Es muy fácil de usar y ofrece herramientas para colorear, estilos y la posición en el terminal. Lo que necesita 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)

Descargar y documentación aquí

o puede instalar con pip:

pip install blessings

Si estás usando Python 3.3 o superior, me gustaría recomendar la incorporada en get_terminal_size() como ya se ha recomendado. Sin embargo, si usted está atascado con una versión anterior y desea una forma sencilla y multiplataforma de hacer esto, se podía usar asciimatics . Este paquete es compatible con versiones de Python de nuevo a 2.7 y utiliza opciones similares a las sugeridas anteriormente para obtener el / tamaño actual consola de terminal.

Simplemente construir su clase Screen y usar la propiedad dimensions para obtener la altura y anchura. Esto se ha demostrado que funciona en Linux, OSX y Windows.

Oh - y la información completa aquí:. Soy el autor, por lo que no dude en abrir un nuevo problema si usted tiene problemas para conseguir que esto funcione

Aquí está una versión que debe ser compatible con Linux y Solaris. Sobre la base de los postes y commments de madchine . Requiere el módulo de subproceso.

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')
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top