Title: Use terminal width by default in pprint
Type: enhancement Stage: patch review
Components: Library (Lib) Versions: Python 3.7
Status: open Resolution:
Dependencies: Superseder:
Assigned To: Nosy List: eric.araujo, eryksun, fdrake, josh.r, rhettinger, serhiy.storchaka, xiang.zhang
Priority: normal Keywords:

Created on 2017-04-05 16:29 by serhiy.storchaka, last changed 2017-09-01 23:20 by eric.araujo.

Pull Requests
URL Status Linked Edit
PR 1008 open serhiy.storchaka, 2017-04-05 16:42
Messages (12)
msg291187 - (view) Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) Date: 2017-04-05 16:29
pprint() uses width=80 by default. But default output stream is sys.stdout which often is connected to a terminal, and terminals now usually have larger width than 80 columns.

Proposed patch change the default value of the width parameter in pprint(). If the width is specified and the output is a terminal, then the width of the terminal is used.
msg291195 - (view) Author: Raymond Hettinger (rhettinger) * (Python committer) Date: 2017-04-05 21:37
Some thoughts:

* I'm not sure the terminal width will always be knowable, for example when using IDLE.

* I often need smaller widths when printing short dicts and lists.  The smaller widths better show the parallel structure.  I think having it fill the width of my screen is rarely what I would want.

* ISTM, this will cause reproducibility issues, esp for doctests.
msg291196 - (view) Author: Fred Drake (fdrake) (Python committer) Date: 2017-04-05 21:45
This is not a problem for doctests, since the output stream is not a terminal; the check for terminal-ness seems reasonable.  (Though I don't have any idea if it works on Windows, but it seems properly factored.)
msg291197 - (view) Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) Date: 2017-04-05 21:58
* In IDLE sys.stdout.isatty() returns True, but sys.stdout.fileno() raises an exception. Terminal width can't be determined and the default 80 is used.

* You always can pass explicit width to pprint. This may be needed even with default width 80. Now on wide a terminal wider 80 columns you have unused space than can cause unneeded wrapping. On a terminal narrower 80 columns the pprint() output is formatted incorrectly and is wrapped twice: by pprint() and by terminal.

* The output in doctests is not connected to a terminal.
msg291198 - (view) Author: Eryk Sun (eryksun) * (Python triager) Date: 2017-04-05 22:07
> Though I don't have any idea if it works on Windows, but it seems 
> properly factored.

Generally it should. However, os.get_terminal_size is unnecessarily limited to the standard handles with a hard-coded mapping 0 => StandardInput, 1 => StandardOutput, and 2 => StandardError, and otherwise raises ValueError. Example failure:

    >>> fd ='conout$', os.O_RDWR)
    >>> os.isatty(fd)
    >>> os.get_terminal_size(fd)
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    ValueError: bad file descriptor

There is no need to involve the standard handles. It should call _get_osfhandle(fd).
msg291238 - (view) Author: Raymond Hettinger (rhettinger) * (Python committer) Date: 2017-04-06 17:24
After more thought, put me down for -1 on this proposal.   

I use pprint() quite a bit when teaching Python courses.  I expect that 100% of the time that users are following the live examples, I will get stopped and asked why their output is different from mine.

Also, I question the usefulness of the auto-resizing.  When I pprint a dir() listing or some such, the intended effect is almost always that I want a vertical presentation.  If a horizontal one-liner was desired, I would have used print() instead.  ISTM, this proposal is out of touch with the actual needs and desires of users.

As a reference point, consider that IPython pretty prints output by default and is not terminal width sensitive.
msg291239 - (view) Author: Raymond Hettinger (rhettinger) * (Python committer) Date: 2017-04-06 17:45
One other thought:  This module has a very long history. It is widely used, has had many feature requests and bug reports, but this particular feature has never been requested.  That should tell us something about whether there is an actual need.  To me, this seems like a new made-up requirement, invented in complete isolation from users.
msg291240 - (view) Author: Fred Drake (fdrake) (Python committer) Date: 2017-04-06 17:55
I wouldn't go so far as to say it's never come up; it's something I've thought about a number of times, and I've waffled on it a few times.

It's not fundamentally unreasonable to want it to adapt to the current terminal window, though I think it would be in a minority among the Unix command line tools that I use.

Raymond's point about potentially confusing students is an important one, though.  If adaptive behavior is sufficiently desirable, the module should check the value of an environment variable, and default to the current behavior.  PYTHONADAPTIVEPPRINT ?
msg291243 - (view) Author: Josh Rosenberg (josh.r) * (Python triager) Date: 2017-04-06 18:06
If you want the dir listing output in a column, you're just relying on your listing to be wider than 80 characters, it still doesn't columnize unless you pass that point.

Personally, I feel if I made the terminal wider, I'd like to actually use that width.

I suppose an alternative, if you really don't want autosizing, is to make auto-sizing supported without having to explicitly call getterminalsize over and over, perhaps by creating some sentinel value (pprint.AUTOWIDTH or whatever) to make it trivial to do (or to allow those who desire it to use partial binding to make it the default for a session up front).
msg291244 - (view) Author: Josh Rosenberg (josh.r) * (Python triager) Date: 2017-04-06 18:08
Thus, you keep your default behavior of width=80, while I just add the following to my PYTHONSTARTUP file:

from functools import partial
from pprint import pprint, AUTOWIDTH

pprint = partial(pprint, width=AUTOWIDTH)

and we both get what we want.
msg291248 - (view) Author: Xiang Zhang (xiang.zhang) * (Python committer) Date: 2017-04-07 03:43
I use screens and usually like to open a terminal to fill the screen. One of my use case is changed by this patch from:

             'manufacturers_specifications': '2U 2*Intel Xeon E5-2603 4核 8*8G '
                                             'DDR3-1333 ECC 1.35v,12*300G 15K '
                                             'RPM 3.5寸 SAS,RAID '
                                             '卡带电池cache大于等于1GB,支持 Raid0 1 10 5 '
                                             '6 50 60[D23]',


             'manufacturers_specifications': '2U 2*Intel Xeon E5-2603 4核 8*8G DDR3-1333 ECC 1.35v,12*300G 15K RPM 3.5寸 SAS,RAID 卡带电池cache大于等于1GB,支持 Raid0 1 10 5 6 50 60[D23]',

Actually looks not bad. But why change the default behaviour? Can we provide this as a bonus and keep the default behaviour? Current defaults  80 is not unreasonable even for large terminals. If users prefer long lines and don't want to choose an arbitrary number, they could use this feature.
msg301157 - (view) Author: Éric Araujo (eric.araujo) * (Python committer) Date: 2017-09-01 23:20
I was about to open the same issue!  I tend to print nested data structures for debugging; having lists take up a lot of vertical screen estate and leave unused all the horizontal space is an annoyance, so that I regularly have to go back and add the width param.

Contrary to Fred, I think my tools tend to use the available width, but then I think that auto-width is a good behaviour for a tool, but maybe not a good change for a general library.  Raymond’s note about students is also an important point.  I don’t like adding envvars to control the behaviour of a module function at a distance, or magic constants; if I can pass a constant, I can pass a number (for quick debugging) or handle getting the terminal width at a higher layer (in a real command-line program).  For my debugging use case, maybe it’s time I switch to q (on PyPI) and save even more typing.

Even though I was about to request the same feature, I’m now -0.
Date User Action Args
2017-09-01 23:20:06eric.araujosetnosy: + eric.araujo
messages: + msg301157
2017-04-07 03:43:54xiang.zhangsetnosy: + xiang.zhang
messages: + msg291248
2017-04-06 18:08:41josh.rsetmessages: + msg291244
2017-04-06 18:06:09josh.rsetnosy: + josh.r
messages: + msg291243
2017-04-06 17:55:58fdrakesetmessages: + msg291240
2017-04-06 17:45:08rhettingersetmessages: + msg291239
2017-04-06 17:24:43rhettingersetmessages: + msg291238
2017-04-05 22:07:04eryksunsetnosy: + eryksun
messages: + msg291198
2017-04-05 21:58:11serhiy.storchakasetmessages: + msg291197
2017-04-05 21:45:22fdrakesetmessages: + msg291196
2017-04-05 21:37:20rhettingersetmessages: + msg291195
2017-04-05 16:42:30serhiy.storchakasetpull_requests: + pull_request1176
2017-04-05 16:29:16serhiy.storchakacreate