Best way of finding terminal width/height?

Grant Edwards grante at visi.com
Tue Feb 7 13:06:43 EST 2006


On 2006-02-07, Joel Hedlund <joel.hedlund at gmail.com> wrote:

>> You just call the failed read() or write() again.  Unless
>> there's some way that the read/write partially succeeded and
>> you don't have any way to know how many bytes were
>> read/written, If that's the case then Python's "file" object
>> read and write would appear to be broken by design.
>
> Wow... I tried to set up an example that would fail, and it
> didn't. It seems the test only fails if I use the keyboard to
> cram stuff into stdin, and not if stdin is a regular pipe. 

That's what I'd expect.  Resizing the terminal should have no
effect on read() calls that are pending on other things.

> Could this perhaps be some kind of misbehavior on behalf of my
> terminal emulator (GNOME Terminal 2.12.0 in Ubuntulinux 5.10)?

Nope.  Resign the terminal will abort pending I/O operations on
that terminal.  It won't terminal I/O operations pending on
other devices/files.

> Then run the prog and pipe a large chunk of text into stdin, and redirect stdout to a file:
>
> $ cat /a/large/text/file | python winch.py > copy.of.the.large.file
>
> Now, what happens for me is exactly what I wanted. I can
> resize the window as much as I like, and a diff 

Sure.

> $ diff /a/large/text/file copy.of.the.large.file
>
> comes up empty. A perfectly good copy.
>
> However, if I do this instead (try to use keyboard to push stuff into stdin):
>
> $ python winch.py > copy.of.the.large.file
>
> I expect python not to return until I press Ctrl-D on my
> keyboard,

sys.stdin.read() will return when there's an EOF or when the
underyling read() call is aborted by a signal.

> but it does return as soon as I enter more than one
> line of text and then resize the window (one unterminated line
> is ok). 
>
> Example text to type in:
> moo moo
> cow cow
>
> As soon as I have typed in something that includes a newline
> charater through the keyboard and try to resize the terminal,
> sys.stdin.read() will return whatever I put in no far and no
> exception raised.

Yup.  That does indeed appear to be the way it works. :)

> Weird. Could it in fact my terminal that's screwing things up
> for me?

No.

Try this out:

----------------------------------------------------------------------
#!/usr/bin/python
import signal, os, sys

_bTerminalSizeChanged = False

def report_terminal_size_change(signum, frame):
    global _bTerminalSizeChanged
    _bTerminalSizeChanged = True

signal.signal(signal.SIGWINCH, report_terminal_size_change)

while True:
    try:
        s = sys.stdin.read()
        if not s:
            break
        sys.stdout.write(s)
    except IOError:
        sys.stderr.write("IOError\n")
    if _bTerminalSizeChanged:
        sys.stderr.write("SIGWINCH recevied\n")
        _bTerminalSizeChanged = False
----------------------------------------------------------------------

In that example, I handle IOError on write with the same
exception handler as the one for read.  That may not be exactly
what you want to do, but it does demonstrate what
window-resizing does.

When the window is resized, the SIGWINCH handler will be
called.  A pending read() may abort with an IOError, or it may
just return some buffered data.

-- 
Grant Edwards                   grante             Yow!  Send your questions
                                  at               to "ASK ZIPPY", Box 40474,
                               visi.com            San Francisco, CA 94140,
                                                   USA



More information about the Python-list mailing list