How to get Linux console window width in Python

ID : 10320

viewed : 34

Tags : pythonlinuxconsoleterminalwidthpython

Top 5 Answer for How to get Linux console window width in Python

vote vote

93

Not sure why it is in the module shutil, but it landed there in Python 3.3, Querying the size of the output terminal:

>>> import shutil >>> shutil.get_terminal_size((80, 20))  # pass fallback os.terminal_size(columns=87, lines=23)  # returns a named-tuple 

A low-level implementation is in the os module. Also works in Windows.

A backport is now available for Python 3.2 and below:

vote vote

90

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

uses the 'stty size' command which according to a thread on the python mailing list is reasonably universal on linux. It opens the 'stty size' command as a file, 'reads' from it, and uses a simple string split to separate the coordinates.

Unlike the os.environ["COLUMNS"] value (which I can't access in spite of using bash as my standard shell) the data will also be up-to-date whereas I believe the os.environ["COLUMNS"] value would only be valid for the time of the launch of the python interpreter (suppose the user resized the window since then).

(See answer by @GringoSuave on how to do this on python 3.3+)

vote vote

80

use

import console (width, height) = console.getTerminalSize()  print "Your terminal's width is: %d" % width 

EDIT: oh, I'm sorry. That's not a python standard lib one, here's the source of console.py (I don't know where it's from).

The module seems to work like that: It checks if termcap is available, when yes. It uses that; if no it checks whether the terminal supports a special ioctl call and that does not work, too, it checks for the environment variables some shells export for that. This will probably work on UNIX only.

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]) 
vote vote

63

Code above didn't return correct result on my linux because winsize-struct has 4 unsigned shorts, not 2 signed shorts:

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 and hp should contain pixel width and height, but don't.

vote vote

55

It's either:

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

The shutil function is just a wrapper around os one that catches some errors and set up a fallback, however it has one huge caveat - it breaks when piping!, which is a pretty huge deal.
To get terminal size when piping use os.get_terminal_size(0) instead.

First argument 0 is an argument indicating that stdin file descriptor should be used instead of default stdout. We want to use stdin because stdout detaches itself when it is being piped which in this case raises an error.

I've tried to figure out when would it makes sense to use stdout instead of stdin argument and have no idea why it's a default here.

Top 3 video Explaining How to get Linux console window width in Python

Related QUESTION?