Is shutil.get_terminal_size useless?

Steve D'Aprano steve+python at pearwood.info
Wed Feb 1 20:24:22 EST 2017


On Sun, 29 Jan 2017 04:58 am, Chris Angelico wrote:

> On Sun, Jan 29, 2017 at 3:15 AM, Steve D'Aprano
> <steve+python at pearwood.info> wrote:
>> On Sat, 28 Jan 2017 10:50 pm, Chris Angelico wrote:
>>
>>> On Sat, Jan 28, 2017 at 9:49 PM, Steve D'Aprano
>>> <steve+python at pearwood.info> wrote:
>>>> The terminal size doesn't change just because I'm piping output to
>>>> another process. Using the terminal size as a proxy for "being piped"
>>>> is sheer insanity.
>>>
>>> In a sense, there _is no_ terminal size when you're being piped to
>>> another process.
>>
>> In which sense, and why do you think it is relevant?
>>
>> There clearly is a terminal, because that's where I'm running the code.
>> Regardless of whether I pipe it to grep or cat or something else, the
>> output from *that* process still ends up in the same terminal that I
>> typed the command in.
> 
> No, not automatically. I've written plenty of programs that accept
> input via a pipe and don't display any of it. 

Well of course if your program doesn't produce any output, the output
doesn't go to stdout. Because there is none.


> Just because someone 
> types "command1 | command2", you can't assume that the terminal
> command2 is outputting to is the same size as the one command1 should
> be outputting to.

I'm not assuming anything of the sort. Obviously command2 can send output
where it likes, including /dev/null, or simply not produce any output. And
as I've *repeatedly* acknowledged, there are circumstances where there is
no terminal at all. And shutil does the wrong thing then too: it returns an
arbitrary size, instead of raising.

(Of course we should be able to explicitly pass a default to
shutil.get_terminal_size() if we wish.)


> 
>>> etc, etc, etc, etc. It's
>>> not a proxy for "being piped" - it's that when your output isn't going
>>> to a terminal, asking "what is my terminal size" isn't particularly
>>> productive.
>>
>> Then explain why os.get_terminal_size() returns the correct answer.

No answer Chris?

You've spent a lot of time telling me that asking for the terminal size
doesn't even make sense for the exact circumstances where
os.get_terminal_size() not only returns a size, but the *correct* size.

And, of course, it also correctly raises an exception in those unusual cases
where there truly is no terminal, or it is unknowable.


>> The output might not be going to a terminal (not directly at least) but
>> the question isn't "what's the size of the terminal that output is going
>> to". The question is "what's the size of the terminal that this process
>> is running in", and that has an answer regardless of where output is
>> piped.
> 
> Processes aren't always running "in" terminals, though. That's my
> point. A terminal is not a fundamental feature of a process.

And I have acknowledged this, oh, about a million times.

But when the processes *are* running in terminals, shutil should return the
size of the terminal, not some arbitrary made up size. Otherwise it is
useless.


>>> Would you expect a cronjob to use the terminal size when you
>>> most recently edited crontab? No.
>>
>> Of course not -- the terminal where you edited crontab is not where the
>> process is running. Why would it be the least bit relevant?
> 
> So where *is* that process running? What terminal is it in? 

There isn't one.


> Don't you 
> see how similar this is to the pipe situation

No. os.get_terminal_size() is correctly able to return the terminal size in
the pipe situation, even in a *double* pipe situation (you need to look at
stderr rather than stdin or stout). I'm not sure if it is able to cope with
situations where all three of std[in|out|err] are redirected, but that's
okay. I'm a realist: if there are scenarios where the terminal size is
unknowable, then so be it.

But a simple pipe is not one of those cases.


> - sure, there might be a  
> terminal that the program was invoked from, but it's utterly
> irrelevant to how the program actually runs.

Except that in the pipe situation, "how the program actually runs" *is* in a
terminal.


> >> You might well be a completely background process.
>>
>> And if that background process is running in a terminal? What's your
>> point?
> 
> Background processes don't have terminal access.

Really? I think you are wrong:

[steve at ando ~]$ cat bkg.py
from os import get_terminal_size
print(get_terminal_size(0))
[steve at ando ~]$ python3.5 bkg.py &
[1] 13776
[steve at ando ~]$ os.terminal_size(columns=116, lines=29)

[1]+  Done                    python3.5 bkg.py
[steve at ando ~]$


Looks like the background process is perfectly able to return the terminal
size, and not an arbitrary number either, it has the correct size.


> Whether it's a daemon 
> or something started as "commandname >/dev/null 2>/dev/null </dev/null
> &" from bash, it doesn't have access to a terminal.

As I've repeatedly said, if there are situations where the terminal size is
genuinely unknowable, then so be it.

But shutil fails even when the terminal size *is* knowable. How is this
useful?


> Please don't assume that every program has a controlling UI.

I'm not, and I haven't.


> I get 
> enough of that mentality from the people I support on Windows, where
> the fundamental assumption of people seems to be that there's a GUI
> for everything. There isn't. And there isn't always a terminal either.
> Processes in the middle of pipelines *do not have* terminals.

Sometimes they do.




-- 
Steve
“Cheer up,” they said, “things could be worse.” So I cheered up, and sure
enough, things got worse.




More information about the Python-list mailing list