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
> (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.
I've been doing it with curses.tigetnum('cols') (and the other dimension, which I didn't need, is curses.tigetnum('lines')). You need to call curses.setupterm() before you can use those (and be prepared to handle exceptions, e.g. if $TERM is set to a nonsense value).
You can find the working code at http://zope3.pov.lt/trac/browser/zope.testrunner/trunk/src/zope/testrunner/formatter.py?rev=117583#L364
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.
correction, glance uses get_terminal_size() exactly once in …/glance/common/animation.py to display a progress bar during upload.
Doesn't work correctly if one of $LINES, $COLUMNS is set, but not both.
Out of curiosity, why did you choose 999 for error code?
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: