Comment obtenir la largeur de fenêtre de la console Linux en Python
y a-t-il un moyen en python de déterminer programmatiquement la largeur de la console? Je veux dire le nombre de caractères qui s'inscrit dans une ligne sans emballage, pas la largeur en pixels de la fenêtre.
Modifier
à la recherche d'une solution qui fonctionne sur Linux
14 réponses
import os
rows, columns = os.popen('stty size', 'r').read().split()
utilise la commande "stty size" qui selon un thread sur la liste de diffusion python est raisonnablement universel sur linux. Il ouvre la commande' stty size 'en tant que Fichier,' reads ' à partir de celle-ci, et utilise une simple fente de chaîne de caractères pour séparer les coordonnées.
contrairement à l'os.environ ["colonnes"] valeur (à laquelle je ne peux pas accéder malgré l'utilisation de bash comme shell standard) les données seront également à jour alors que je crois que le OS.environ["COLONNES"] valeur ne serait valide que pour le moment du lancement de l'interpréteur python (supposons que l'utilisateur redimensionné la fenêtre depuis).
Je ne sais pas pourquoi il est dans le module shutil
, mais il a atterri là en Python 3.3, Querying la taille du terminal de sortie :
>>> import shutil
>>> shutil.get_terminal_size((80, 20)) # pass fallback
os.terminal_size(columns=87, lines=23) # returns a named-tuple
une implémentation de bas niveau se trouve dans le module os.
un backport est maintenant disponible pour Python 3.2 et inférieur:
utiliser
import console
(width, height) = console.getTerminalSize()
print "Your terminal's width is: %d" % width
MODIFIER : oh, je suis désolé. Ce n'est pas un Python standard lib one, voici la source de console.py (Je ne sais pas d'où ça vient).
le module semble fonctionner comme cela: il vérifie si termcap
est disponible, quand Oui. Il utilise cela; si non il vérifie si le terminal supporte un appel spécial ioctl
et cela ne fonctionne pas, aussi, il vérifie pour les variables d'environnement quelques shells exportez pour ça.
Cela ne fonctionnera probablement que sur 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])
Code ci-dessus n'a pas retourné le résultat correct sur mon linux parce que winsize-struct A 4 shorts non signés, pas 2 shorts signés:
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 et hp doivent contenir la largeur et la hauteur des pixels, mais ne le font pas.
j'ai cherché partout et j'ai trouvé une solution pour windows à:
http://code.activestate.com/recipes/440694-determine-size-of-console-window-on-windows /
et une solution pour linux ici.
voici donc une version qui fonctionne à la fois sur linux, os x et 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
à partir de Python 3.3 c'est tout droit: 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
on dirait Qu'il y a des problèmes avec ce code, Johannes:
-
getTerminalSize
doitimport os
- qu'est-ce que
env
? on diraitos.environ
.
de plus, pourquoi changer lines
et cols
avant de revenir? Si TIOCGWINSZ
et stty
disent tous les deux lines
puis cols
, je dis de laisser tomber. Cela m'a embrouillé pendant une bonne 10 minutes avant que je remarqué l'incohérence.
Sridhar, Je n'ai pas eu cette erreur quand j'ai pipé la sortie. Je suis presque sûr qu'il est pris correctement dans l'essai-sauf.
pascal, "HHHH"
ne fonctionne pas sur ma machine, mais "hh"
le fait. J'ai eu du mal à trouver de la documentation pour cette fonction. On dirait que ça dépend de la plateforme.
chochem, incorporated.
voici ma version:
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)
beaucoup d'implémentations de Python 2 échoueront s'il n'y a pas de terminal de contrôle lorsque vous appelez ce script. Vous pouvez vérifier sys.la sortie standard stdout.isatty () pour déterminer si c'est en fait un terminal, mais cela exclura un tas de cas, donc je crois que le moyen le plus pythonique pour comprendre la taille du terminal est d'utiliser le paquet de malédictions intégré.
import curses
w = curses.initscr()
height, width = w.getmaxyx()
c'est soit:
import os
columns, rows = os.get_terminal_size(0)
# or
import shutil
columns, rows = shutil.get_terminal_size()
la fonction shutil
n'est qu'un enveloppeur autour de os
qui capte quelques erreurs et met en place un repli, cependant il a une énorme mise en garde - il casse lorsque la tuyauterie! , ce qui est assez énorme.
Pour obtenir la taille du terminal lorsque la tuyauterie utiliser os.get_terminal_size(0)
à la place.
Premier argument 0
est un argument indiquant que le fichier stdin le descripteur doit être utilisé à la place du stdout par défaut. Nous voulons utiliser stdin parce que stdout se détache quand il est pipé qui soulève dans ce cas soulève une erreur..
J'ai essayé de comprendre quand il serait logique d'utiliser stdout à la place de l'argument stdin et n'ont aucune idée de la raison pour laquelle c'est un défaut ici.
la réponse de @reannual fonctionne bien, mais il y a un problème avec elle: os.popen
est maintenant déprécié . Le module subprocess
devrait être utilisé à la place, donc voici une version du code de @reannual qui utilise subprocess
et répond directement à la question (en donnant la largeur de la colonne directement comme un int
:
import subprocess
columns = int(subprocess.check_output(['stty', 'size']).split()[1])
testé sur OS X 10.9
j'ai essayé la solution d'ici qui appelle à stty size
:
columns = int(subprocess.check_output(['stty', 'size']).split()[1])
cependant cela a échoué pour moi parce que je travaillais sur un script qui attend des entrées redirigées sur stdin, et stty
se plaindrait que "stdin n'est pas un terminal" dans ce cas.
j'ai été capable de le faire fonctionner comme ceci:
with open('/dev/tty') as tty:
height, width = subprocess.check_output(['stty', 'size'], stdin=tty).split()
Essayer "bénédictions"
je cherchais la même chose. Il est très facile à utiliser et offre des outils pour la coloration, le style et le positionnement dans le terminal. Ce dont vous avez besoin est aussi simple que:
from blessings import Terminal
t = Terminal()
w = t.width
h = t.height
fonctionne comme un charme sous Linux. (Je ne suis pas sûr de MacOSX et Windows)
Téléchargement et documentation ici
ou vous pouvez l'installer avec pip:
pip install blessings
si vous utilisez Python 3.3 ou plus, je recommande l'intégration get_terminal_size()
comme déjà recommandé. Cependant, si vous êtes coincé avec une version plus ancienne et que vous voulez un moyen simple et multiplate-forme de le faire, vous pouvez utiliser asciimatics . Ce paquet prend en charge les versions de Python de retour à 2.7 et utilise des options similaires à celles suggérées ci-dessus pour obtenir la taille du terminal/console actuelle.
il vous suffit de construire votre classe Screen
et d'utiliser le dimensions
propriété pour obtenir la hauteur et la largeur. Il a été prouvé que cela fonctionne sous Linux, OSX et Windows.
Oh - et la divulgation complète: je suis l'auteur, n'hésitez pas à ouvrir un nouveau problème si vous avez des problèmes pour obtenir que cela fonctionne.
Voici une version qui devrait être compatible Linux et Solaris. D'après les billets et les engagements de madchine . Nécessite le module de sous-processus.
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')