Is there a way in python to programmatically determine the width of the console? I mean the number of characters that fits in one line without wrapping, not the pixel width of the window.
Edit
Looking for a solution that works on Linux
Is there a way in python to programmatically determine the width of the console? I mean the number of characters that fits in one line without wrapping, not the pixel width of the window.
Edit
Looking for a solution that works on Linux
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():
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:
cr = (25, 80)
return int(cr[1]), int(cr[0])
Depending on your shell (I know that bash, at least, does this), you can access the terminal size using the ROWS
and COLUMNS
environment variables. I don't know of a Windows equivalent.
import os
print os.environ["COLUMNS"]
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).
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.
It looks like there are some problems with that code, Johannes:
getTerminalSize
needs to import os
env
? looks like os.environ
.Also, why switch lines
and cols
before returning? If TIOCGWINSZ
and stty
both say lines
then cols
, I say leave it that way. This confused me for a good 10 minutes before I noticed the inconsistency.
Sridhar, I didn't get that error when I piped output. I'm pretty sure it's being caught properly in the try-except.
pascal, "HHHH"
doesn't work on my machine, but "hh"
does. I had trouble finding documentation for that function. It looks like it's platform dependent.
chochem, incorporated.
Here's my 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)