programa - ejecutar python en linux
Cómo obtener el ancho de la ventana de la consola de Linux en Python (14)
¿Hay una manera en Python para determinar mediante programación el ancho de la consola? Me refiero al número de caracteres que caben en una línea sin ajuste, no al ancho de píxel de la ventana.
Editar
Buscando una solución que funcione en Linux
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 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'')
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 como 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://.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
Comenzando en 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
Desde aquí estaba probando la solución que llama al stty size
:
columns = int(subprocess.check_output([''stty'', ''size'']).split()[1])
Sin embargo, esto no stty
porque estaba trabajando en un script que espera una entrada redirigida en stdin, y stty
se quejaría de que "stdin no es un terminal" en ese caso.
Pude hacerlo funcionar así:
with open(''/dev/tty'') as tty:
height, width = subprocess.check_output([''stty'', ''size''], stdin=tty).split()
El código anterior no devolvió el resultado correcto en mi linux porque winsize-struct tiene 4 cortos sin firma, 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 el ancho y la altura de los píxeles, pero no lo hacen.
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 solo una envoltura alrededor del shutil
operativo que shutil
algunos errores y establece una reserva, sin embargo, tiene una gran advertencia: ¡ se rompe cuando se canaliza! , que es una gran cosa
Para obtener el tamaño de la terminal cuando la tubería use en su lugar os.get_terminal_size(0)
.
El primer argumento 0
es un argumento que indica que se debe usar el descriptor de archivo estándar en lugar de la salida estándar predeterminada. Queremos usar stdin porque stdout se separa cuando se está canalizando, lo que aumenta en este caso genera un error ...
He intentado averiguar cuándo tendría sentido usar stdout en lugar de un argumento estándar y no tengo idea de por qué es un valor predeterminado aquí.
La respuesta de @ reannual funciona bien, pero hay un problema con eso: os.popen
ahora está en desuso . El módulo de subprocess
debe usarse en su lugar, por lo que aquí hay una versión del código de @ reannual que usa el subprocess
y responde directamente a la pregunta (dando el ancho de la columna directamente como un int
:
import subprocess
columns = int(subprocess.check_output([''stty'', ''size'']).split()[1])
Probado en OS X 10.9
Muchas de las implementaciones de Python 2 aquí fallarán si no hay un terminal de control al llamar a este script. Puede verificar sys.stdout.isatty () para determinar si esto es en realidad un terminal, pero eso excluirá un montón de casos, por lo que creo que la forma más pirónica de averiguar el tamaño del terminal es usar el paquete de curses integrado.
import curses
w = curses.initscr()
height, width = w.getmaxyx()
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 os.
Un backport ahora está disponible para Python 3.2 y más abajo:
Parece que hay algunos problemas con ese código, Johannes:
-
getTerminalSize
necesitaimport os
- que es
env
Parece queos.environ
.
Además, ¿por qué cambiar de lines
y lines
antes de volver? Si TIOCGWINSZ
y stty
dicen lines
luego cols
, digo que lo dejen así. Esto me confundió por unos buenos 10 minutos antes de que notara la inconsistencia.
Sridhar, no recibí ese error cuando canalicé la salida. Estoy bastante seguro de que está siendo atrapado adecuadamente en el intento, excepto.
pascal, "HHHH"
no funciona en mi máquina, pero "hh"
sí funciona. Tuve problemas para encontrar documentación para esa función. Parece que depende de la plataforma.
chochem, incorporado.
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)
Prueba "bendiciones"
Estaba buscando lo mismo. Es muy fácil de usar y ofrece herramientas para colorear, estilizar y posicionar 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 de MacOSX y Windows)
Descarga y documentación here
o puedes instalarlo con pip:
pip install blessings
Si está usando Python 3.3 o superior, recomendaría el get_terminal_size()
como ya se recomendó. Sin embargo, si está atascado con una versión anterior y desea una forma simple y multiplataforma de hacerlo, podría usar asciimatics . Este paquete admite versiones de Python de regreso a 2.7 y usa opciones similares a las sugeridas anteriormente para obtener el tamaño actual de la terminal / consola.
Simplemente construya su clase de Screen
y use la propiedad de las dimensions
para obtener la altura y el ancho. Se ha comprobado que esto funciona en Linux, OSX y Windows.
Ah, y la divulgación completa aquí: soy el autor, así que no dude en abrir un nuevo número si tiene algún problema para que esto funcione.
utilizar
import console
(width, height) = console.getTerminalSize()
print "Your terminal''s width is: %d" % width
EDIT : oh, lo siento. Esa no es una versión estándar de python, aquí está la fuente de console.py (no sé de dónde viene).
El módulo parece funcionar así: comprueba si termcap
está disponible, cuando sí. Utiliza eso; si no, comprueba si el terminal admite una ioctl
especial y eso no funciona, también verifica las variables de entorno que algunos shells exportan. 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])
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 ''tamaño stty'' como un archivo, ''lee'' desde él, y usa una simple división de cadenas para separar las coordenadas.
A diferencia del valor os.environ ["COLUMNAS"] (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 os.environ ["COLUMNAS"] El valor solo sería válido durante el momento del lanzamiento del intérprete de Python (suponga que el usuario redimensionó la ventana desde entonces).