Existe-t-il un moyen dans python de déterminer par programme la largeur de la console? Je veux dire le nombre de caractères pouvant être insérés dans une ligne sans le retour à la ligne, pas la largeur en pixels de la fenêtre.
Modifier
Vous recherchez une solution qui fonctionne sous Linux
import os
rows, columns = os.popen('stty size', 'r').read().split()
utilise la commande 'stty size' qui, selon n fil de la liste de diffusion python = est raisonnablement universelle sur linux. Elle ouvre la commande 'stty size' sous forme de fichier , "lit", et utilise une simple scission de chaîne pour séparer les coordonnées.
Contrairement à la valeur os.environ ["COLUMNS"] (à laquelle je ne peux pas accéder malgré l'utilisation de bash comme shell standard), les données sont également à jour, alors que je crois que os.environ ["COLUMNS"] valeur ne serait valide que pour le moment du lancement de l’interprète python (supposons que l’utilisateur redimensionne la fenêtre depuis lors).
Vous ne savez pas pourquoi il est dans le module shutil
, mais il a atterri dans Python 3.3, Interrogation de 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:
utilisation
import console
(width, height) = console.getTerminalSize()
print "Your terminal's width is: %d" % width
ÉDITER : oh, je suis désolé. Ce n'est pas un python lib standard, voici la source de console.py (je ne sais pas d'où il vient).
Le module semble fonctionner comme ça: il vérifie si termcap
est disponible, si oui. Il utilise ça si non, il vérifie si le terminal prend en charge un appel spécial ioctl
et si cela ne fonctionne pas, il vérifie également les variables d'environnement exportées par certains shells. Cela ne fonctionnera probablement que sous 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])
Le code ci-dessus n'a pas retourné le résultat correct sur mon linux car 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 une largeur et une hauteur en pixels, mais ne le faites pas.
J'ai cherché autour et 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 __== "__main__":
sizex,sizey=getTerminalSize()
print 'width =',sizex,'height =',sizey
À partir de Python 3.3, c’est simple: 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
C'est soit:
import os
columns, rows = os.get_terminal_size(0)
# or
import shutil
columns, rows = shutil.get_terminal_size()
La fonction shutil
est juste un wrapper autour de os
qui détecte certaines erreurs et met en place un repli, mais elle a un énorme inconvénient - elle se casse lors du piping!, ce qui est une très grosse affaire.
Pour obtenir la taille du terminal lors de la tuyauterie, utilisez os.get_terminal_size(0)
à la place.
Le premier argument 0
Est un argument indiquant que le descripteur de fichier stdin doit être utilisé à la place de la commande standard stdout. Nous voulons utiliser stdin parce que stdout se détache quand il est en cours de transmission, ce qui soulève dans ce cas une erreur.
J'ai essayé de comprendre quand il serait judicieux d'utiliser stdout au lieu d'argument stdin et je ne sais pas pourquoi c'est un défaut ici.
Il semble y avoir quelques problèmes avec ce code, Johannes:
getTerminalSize
a besoin de import os
env
? ressemble à os.environ
.Aussi, pourquoi passer lines
et cols
avant de revenir? Si TIOCGWINSZ
et stty
disent tous deux lines
alors cols
, je dis qu'il en soit ainsi. Cela m'a confondu pendant une bonne dizaine de minutes avant que je remarque l'incohérence.
Sridhar, je n'ai pas eu cette erreur quand j'ai transmis la sortie. Je suis à peu près sûr que ça se passe correctement dans l'essai, sauf.
Pascal, "HHHH"
ne fonctionne pas sur ma machine, mais "hh"
Est-ce que. J'ai eu du mal à trouver de la documentation pour cette fonction. Il semble que cela dépende de la plate-forme.
chochem, incorporé.
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)
De nombreuses implémentations de Python 2) ici échoueront s'il n'y a pas de terminal de contrôle lorsque vous appelez ce script. Vous pouvez vérifier sys.stdout.isatty () pour déterminer s'il s'agit bien d'un terminal, mais cela exclura un grand nombre de cas, je pense donc que le moyen le plus pythonique de déterminer la taille du terminal consiste à utiliser le paquetage curses intégré.
import curses
w = curses.initscr()
height, width = w.getmaxyx()
J'essayais la solution d'ici qui appelle à stty size
:
columns = int(subprocess.check_output(['stty', 'size']).split()[1])
Cependant, cela a échoué pour moi car je travaillais sur un script qui attend une entrée redirigée sur stdin, et stty
se plaindrait que "stdin n'est pas un terminal" dans ce cas.
J'ai pu le faire fonctionner comme ceci:
with open('/dev/tty') as tty:
height, width = subprocess.check_output(['stty', 'size'], stdin=tty).split()
Si vous utilisez Python 3.3 ou supérieur, je recommanderais le get_terminal_size()
intégré] comme déjà recommandé. Cependant, si vous êtes coincé avec une version plus ancienne et souhaitez un Pour cela, vous pouvez utiliser asciimatics . Ce paquet supporte les versions de Python de retour à la 2.7 et utilise les mêmes options que celles suggérées ci-dessus pour obtenir la taille actuelle du terminal/de la console.
Construisez simplement votre classe Screen
et utilisez la propriété dimensions
pour obtenir la hauteur et la largeur. Il a été prouvé que cela fonctionnait sous Linux, OSX et Windows.
Oh - et divulgation complète ici: je suis l’auteur, alors n'hésitez pas à ouvrir un nouveau numéro si vous avez des problèmes à le faire fonctionner.
La réponse de @ reannual fonctionne bien, mais elle pose un problème: os.popen
est maintenant obsolète . Le module subprocess
devrait être utilisé à la place. Voici donc une version du code de @ reannual qui utilise subprocess
et répond directement à la question (en donnant directement la largeur de la colonne sous forme de int
:
import subprocess
columns = int(subprocess.check_output(['stty', 'size']).split()[1])
Testé sur OS X 10.9
Essayez les "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
Voici une version qui devrait être compatible avec Linux et Solaris. Basé sur les messages et les commentaires de madchine . Requiert le module de sous-processus.
def termsize (): importer shlex, sous-processus, soit sortie = sous-processus.check_output (shlex.split ('/ bin/stty -a')) m = re.search ('lignes\D + (? P\d +); colonnes\D + (? P\d +);', sortie) si m: renvoie m.group ( 'lignes'), m.group ('colonnes') soulève OSError ('Mauvaise réponse:% s'% (sortie))
>>> termsize () ('40', '100')