getting the terminal size in python

I’m finally getting around to making myself learn python as more than just a read-only language. Working with Openstack kind of requires it.

So far, I like it. Much more than I thought I would as an unrepentant sh and perl using systems geek. And getting over my distaste for the white-space issue is also proving to be much easier than I thought it would (although I still think that block-delimiters like {} make the code easier to read…PyHeresy, I know)

While hacking the /usr/bin/glance command to have less ugly output, and adding a –csv option to list the image index in a usefully parseable format, I needed to figure out how to get the terminal size (height,width).

This, cobbled together from various google search results, seems to work. It’s probably not strictly-correct python idiom, and there’s probably a better way of doing it. Comments and critique are welcome.

def get_terminal_size(fd=1):
    """
    Returns height and width of current terminal. First tries to get
    size via termios.TIOCGWINSZ, then from environment. Defaults to 25
    lines x 80 columns if both methods fail.

    :param fd: file descriptor (default: 1=stdout)
    """
    try:
        import fcntl, termios, struct
        hw = struct.unpack('hh', fcntl.ioctl(fd, termios.TIOCGWINSZ, '1234'))
    except:
        try:
            hw = (os.environ['LINES'], os.environ['COLUMNS'])
        except:  
            hw = (25, 80)

    return hw

def get_terminal_height(fd=1):
    """
    Returns height of terminal if it is a tty, 999 otherwise

    :param fd: file descriptor (default: 1=stdout)
    """
    if os.isatty(fd):
        height = get_terminal_size(fd)[0]
    else:
        height = 999
   
    return height

def get_terminal_width(fd=1):
    """
    Returns width of terminal if it is a tty, 999 otherwise

    :param fd: file descriptor (default: 1=stdout)
    """
    if os.isatty(fd):
        width = get_terminal_size(fd)[1]
    else:
        width = 999

    return width

6 Comments

  1. Brendan Scott

    > (although I still think that block-delimiters like {} make the code easier to read…
    It may take some time, but your prospects for a full recovery are good.

    1. cas

      thanks, i considered using curses but it seems like overkill when all i want is the terminal size

      BTW, I found yesterday that glance already has a get_terminal_size() function hidden away in …/glance/common/utils.py but it doesn't seem to use it anywhere.  It also doesn't use the environment variables.  I've modified it to do so and added my get_terminal_height() and get_terminal_width() functions.

       

    1. cas

      since most terminal programs set both automatically, I don't think that's a big problem….but it wouldn't be too hard to make it default to LINES=25 and COLUMNS=80 to cover that pathological situation.

      999 isn't an error code, it's a max size to be used when the output is redirected so that the output can be as long as it needs to be.  less, for example, can scroll horizontally when the line is longer than the terminal width.  I've found it useful in the past with other programs.

      I've also changed the code so that the environment variables can be used to override termios.TIOCGWINSZ by, e.g., running:

      COLUMNS=132 glance index

Comments are closed.