Best way of finding terminal width/height?

Joel Hedlund joel.hedlund at gmail.com
Wed Feb 8 05:03:15 EST 2006


> sys.stdin.read() will return when ... the
> underyling read() call is aborted by a signal.

Not "return", really? Won't it just pass an exception? I thought that was what I was catching with the "except IOError" part there? I assumed that sys.stdin.read() would only return a value properly at EOF?

It looks to me as if sys.stderr.read() really gets an EOF at the final linebreak fed into the terminal prior to window size change, because the final unterminated line shows up on my shell prompt. Like so:

$ python winch.py
moo moo
cow cowmoo moo
$ cow cow

In this example I type moo moo[ENTER]cow cow on my keyboard and then resize the window.

Now that EOF has to come from somewhere (since there's no IOError or other exception, or the program wouldn't terminate nicely with nothing on stderr) and I'd like to point the blame at the terminal. Or is there something really fishy inside sys.stdin.read() or signal that puts EOFs into streams?

But anyway, as long as this behavior only shows up on interactive operation, the user will likely spot it anyway and can react to it. So I think this code would be pretty safe to use. What do you think?

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

What do you mean by "abort"? I can accept that "aborting" may lead to raising of IOError (which we can catch and retry), but not to arbitrary insertion of EOFs into streams (which we cannot distinguish from the real deal coming from the user).

Also: try your example and enter moo moo[ENTER]cow cow[RESIZE][ENTER][RESIZE]

Thanks again for your help.
/Joel

> 
> 
>>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.
> 



More information about the Python-list mailing list