Re: Is shutil.get_terminal_size useless?
On Thu, Feb 2, 2017 at 12:24 PM, Steve D'Apranowrote: 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. > Because you've already decided in your own mind that one answer is THE correct one, and nothing I say will possibly change that. In my very first post on this subject, I pointed out that shutil and os were returning *different* answers, *both* of which are useful. You persist in insisting that only one of them is useful and correct, and so there's no point responding. Let me redirect this discussion slightly. How do you calculate the square root of a number? >>> (-1) ** 0.5 (6.123233995736766e-17+1j) >>> math.sqrt(-1) Traceback (most recent call last): File "", line 1, in ValueError: math domain error >>> cmath.sqrt(-1) 1j Why does only one of these give the correct answer? If you absolutely INSIST that one is correct, how can anyone argue as to why the others exist? Or is it possible that there are times when you want ValueError and times when you want a complex result? ChrisA -- https://mail.python.org/mailman/listinfo/python-list
Re: Is shutil.get_terminal_size useless?
On Sat, 28 Jan 2017 11:53 pm, Peter Otten wrote: [...] >> I see that as "Hey look, we can fool shutil into returning >> absolute garbage instead of the terminal size!" > > There are valid reasons for temporarily altering the number of columns, > like writing to a file or preparing a code sample. Hmmm... I hadn't thought of that. You're right that there are scenarios where you might wish to tell a process to use a different number of columns (or even lines). Good point. I'm not sure that the given API is a good one, but I accept that the COLUMNS + LINES environment variables could be used to override the actual terminal size. -- Steve “Cheer up,” they said, “things could be worse.” So I cheered up, and sure enough, things got worse. -- https://mail.python.org/mailman/listinfo/python-list
Re: Is shutil.get_terminal_size useless?
On Sun, 29 Jan 2017 04:58 am, Chris Angelico wrote: > On Sun, Jan 29, 2017 at 3:15 AM, Steve D'Aprano >wrote: >> On Sat, 28 Jan 2017 10:50 pm, Chris Angelico wrote: >> >>> On Sat, Jan 28, 2017 at 9:49 PM, Steve D'Aprano >>> 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@ando ~]$ cat bkg.py from os import get_terminal_size print(get_terminal_size(0)) [steve@ando ~]$ python3.5 bkg.py & [1] 13776 [steve@ando ~]$ os.terminal_size(columns=116, lines=29) [1]+ Donepython3.5 bkg.py [steve@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 &" 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
Re: Is shutil.get_terminal_size useless?
On Monday, 30 January 2017 05:37:32 UTC, Steven D'Aprano wrote: > On Monday 30 January 2017 08:12, Serhiy Storchaka wrote: > > > On 28.01.17 10:03, Steve D'Aprano wrote: > >> Is shutil.get_terminal_size useless? When, if ever, should I use it in > >> preference to the os version? If the shutil version is broken, can it be > >> fixed? > > > > Read the history of shutil.get_terminal_size(). All this was discussed. > > > Yes, it was discussed, but not resolved: Antoine Pitrou just closed the task > and declared it done, without resolving the failures I am talking about here. > > http://bugs.python.org/issue13609 > > (Thanks Eryk Sun for the link.) Looks like it was closed with the comment "If you want further features, please open a new issue". It sounds to me like os.get_terminal_size() does what you want, and others find the shutil version useful. But if you have a use case for the shutil version that needs a change in its behaviour, I guess you should open an issue for that. The docs on shutil.get_terminal_size seem pretty clear on what it does (whether you agree with the behaviour or not), so I don't think there's much benefit to proposing changes to the docs alone. Paul -- https://mail.python.org/mailman/listinfo/python-list
Re: Is shutil.get_terminal_size useless?
On Sat, 28 Jan 2017 19:03:42 +1100, Steve D'Aprano wrote: > shutil.get_terminal_size returns the wrong values when you pipe your output > to another process, even it you do so in a terminal. Consider this script: > > > import os > import shutil > print('shutil:', shutil.get_terminal_size(fallback=(999, 999))) > print('os:', os.get_terminal_size(0)) > > > That uses two different methods to get the terminal size. If I run that in a > terminal in the normal way, it works fine, returning the correct size for > my terminal: > > > [steve@ando ~]$ python3.5 test_gts.py > shutil: os.terminal_size(columns=116, lines=29) > os: os.terminal_size(columns=116, lines=29) > > > But if I pipe the output to something else, the shutil version fails to > determine the correct terminal size, and falls back on the default: > > > [steve@ando ~]$ python3.5 test_gts.py | cat > shutil: os.terminal_size(columns=999, lines=999) > os: os.terminal_size(columns=116, lines=29) > > > while the os version gives the correct result. > > Is shutil.get_terminal_size useless? When, if ever, should I use it in > preference to the os version? If the shutil version is broken, can it be > fixed? > > > Thanks to Bernardas Ališauskas: > > http://granitosaurus.rocks/getting-terminal-size.html I can suggest a third approach to try but I have not tried piping it. YMMV. import fcntl import os import struct import termios tty = os.open(os.ctermid(), os.O_RDONLY) ts = struct.unpack("hh", fcntl.ioctl(tty, termios.TIOCGWINSZ, "1234")) os.close(tty) columns = ts[1] rows = ts[0] print(str(columns) + "x" + str(rows)) -- GNU/Linux user #557453 The cow died so I don't need your bull! -- https://mail.python.org/mailman/listinfo/python-list
Re: Is shutil.get_terminal_size useless?
On Monday 30 January 2017 08:12, Serhiy Storchaka wrote: > On 28.01.17 10:03, Steve D'Aprano wrote: >> Is shutil.get_terminal_size useless? When, if ever, should I use it in >> preference to the os version? If the shutil version is broken, can it be >> fixed? > > Read the history of shutil.get_terminal_size(). All this was discussed. Yes, it was discussed, but not resolved: Antoine Pitrou just closed the task and declared it done, without resolving the failures I am talking about here. http://bugs.python.org/issue13609 (Thanks Eryk Sun for the link.) -- Steven "Ever since I learned about confirmation bias, I've been seeing it everywhere." - Jon Ronson -- https://mail.python.org/mailman/listinfo/python-list
Re: Is shutil.get_terminal_size useless?
On Mon, Jan 30, 2017 at 2:16 AM, Steve D'Aprano <steve+pyt...@pearwood.info> wrote: > On Mon, 30 Jan 2017 08:12 am, Serhiy Storchaka wrote: > >> On 28.01.17 10:03, Steve D'Aprano wrote: >>> Is shutil.get_terminal_size useless? When, if ever, should I use it in >>> preference to the os version? If the shutil version is broken, can it be >>> fixed? >> >> Read the history of shutil.get_terminal_size(). All this was discussed. > > Where? See issue 13609: http://bugs.python.org/issue13609 -- https://mail.python.org/mailman/listinfo/python-list
Re: Is shutil.get_terminal_size useless?
On Mon, 30 Jan 2017 08:12 am, Serhiy Storchaka wrote: > On 28.01.17 10:03, Steve D'Aprano wrote: >> Is shutil.get_terminal_size useless? When, if ever, should I use it in >> preference to the os version? If the shutil version is broken, can it be >> fixed? > > Read the history of shutil.get_terminal_size(). All this was discussed. Where? -- Steve “Cheer up,” they said, “things could be worse.” So I cheered up, and sure enough, things got worse. -- https://mail.python.org/mailman/listinfo/python-list
Re: Is shutil.get_terminal_size useless?
On 28.01.17 10:03, Steve D'Aprano wrote: Is shutil.get_terminal_size useless? When, if ever, should I use it in preference to the os version? If the shutil version is broken, can it be fixed? Read the history of shutil.get_terminal_size(). All this was discussed. -- https://mail.python.org/mailman/listinfo/python-list
Re: Is shutil.get_terminal_size useless?
On 2017-01-29, Grant Edwardswrote: > On 2017-01-29, Marko Rauhamaa wrote: > >> Mount? As a regular user? > > Yes, using a "fuse" use-space filesystem, you can mount things as a > normal user. There are a couple ISO9660 fuse implemenations. But, you > can't modify a mounted ISO9660 filesystem. I have read about how to > use a union mount to simulate a writable ISO9660 filesystem, but > that's going to require root (I've never tried it). > > As long as you've got the disk space available, the simplest option is > to unpack the .iso into a directory, modify the files, and then use > mkisofs to create the new .iso image. OK, just one more level of pointless digression... _If_ your ISO image is using syslinux as the bootloader (it probably isn't, it's almost certainly using isolinux -- usually in hybrid mode), then the bootloader stuff is actually an image of a bootable floppy disk. It is sort of "outside" the normal ISO9660 filesystem with a fixed size in a "well known" location. I'm pretty sure you could extract that chunk from the ISO using dd, tweak it, and then put it back into the ISO image without having to mount/extract everything and then recreate a new ISO9660 image. But, it's very probably using isolinux, so the bootloader configuration stuff is actually inside the ISO9660 filesystem tree, and you'll have to extract the whole tree, modify the files, and create a new ISO9660 image. -- Grant -- https://mail.python.org/mailman/listinfo/python-list
Re: Is shutil.get_terminal_size useless?
Chris Angelico: > On Mon, Jan 30, 2017 at 3:44 AM, Marko Rauhamaa wrote: >> Mount? As a regular user? > > Let me see, how much effort are you prepared to go to in order to do > this as a "regular user"... because at some point, "sudo" becomes only > one of many options, including "install another Unix system somewhere > that you are root of". But if you genuinely have to mount as a > non-root user, there's fusermount, which is often capable of loading > up an ISO. > > But honestly, "ssh you@somebox" can be run by anyone, so there's > always a way around the whole not-having-root thing. At the moment, we have found it easiest to create our base OS snapshots with some manual steps. Ideally, we could get rid of the manual steps and just have a python script take the place of the human user. That would be trivial if the distros continued the grand tradition of offering serial consoles out of the box. As it stands, all methods of working serial-interface support in the ISO image would still be more trouble than the manual steps. We also use "Packer" to build virtual machines automatically. That works albeit in a somewhat kludgy manner. As far as I understand, Packer delivers keystrokes to the boot command over VNC but can't interpret the graphical responses but simply trusts that the commands do the right thing with a proper timing. Marko -- https://mail.python.org/mailman/listinfo/python-list
Re: Is shutil.get_terminal_size useless?
On Mon, Jan 30, 2017 at 4:08 AM, Grant Edwardswrote: > As long as you've got the disk space available, the simplest option is > to unpack the .iso into a directory, modify the files, and then use > mkisofs to create the new .iso image. > > I've written scripts like that to build cusotmized bootable ISO images > (usually using systemrescuecd as the starting point). It's not > particulary difficult, but it does burn up a lot of disk space. It's > also rather slow, so when you get into the tweak-build-burn-test cycle > you don't get in a lot of guesses-per-hour. These days, CD images are a tiny proportion of typical hard disk capacities. Every terabyte of disk can hold over a thousand ISOs, and that's assuming they're using the whole disc (~760MB). Several thousand, if they're only part-full images. But the time factor is considerable. Especially if you then have to boot up a VM or something to test it. ChrisA -- https://mail.python.org/mailman/listinfo/python-list
Re: Is shutil.get_terminal_size useless?
On 2017-01-29, Marko Rauhamaawrote: > Mount? As a regular user? Yes, using a "fuse" use-space filesystem, you can mount things as a normal user. There are a couple ISO9660 fuse implemenations. But, you can't modify a mounted ISO9660 filesystem. I have read about how to use a union mount to simulate a writable ISO9660 filesystem, but that's going to require root (I've never tried it). As long as you've got the disk space available, the simplest option is to unpack the .iso into a directory, modify the files, and then use mkisofs to create the new .iso image. I've written scripts like that to build cusotmized bootable ISO images (usually using systemrescuecd as the starting point). It's not particulary difficult, but it does burn up a lot of disk space. It's also rather slow, so when you get into the tweak-build-burn-test cycle you don't get in a lot of guesses-per-hour. -- Grant -- https://mail.python.org/mailman/listinfo/python-list
Re: Is shutil.get_terminal_size useless?
On 2017-01-29, Marko Rauhamaawrote: > Chris Angelico : > >> On Mon, Jan 30, 2017 at 3:28 AM, Marko Rauhamaa wrote: >>> Grant Edwards : >>> On 2017-01-29, Marko Rauhamaa wrote: > I *have* been longing for a serial console in linux distros. Well, all it takes is a tweak to the bootloader to add a kernel "command-line" parameter... >>> >>> Can you give me a short Python script that effects the tweak to an ISO >>> image? I need to run the script as a regular user. >> >> It'd start by mounting it somewhere, and finish by building a new ISO >> with mkisofs, so a shell script would be more appropriate :) > > Mount? As a regular user? https://linux.die.net/man/8/isoinfo -- Grant -- https://mail.python.org/mailman/listinfo/python-list
Re: Is shutil.get_terminal_size useless?
On Mon, Jan 30, 2017 at 3:44 AM, Marko Rauhamaawrote: > Chris Angelico : > >> On Mon, Jan 30, 2017 at 3:28 AM, Marko Rauhamaa wrote: >>> Grant Edwards : >>> On 2017-01-29, Marko Rauhamaa wrote: > I *have* been longing for a serial console in linux distros. Well, all it takes is a tweak to the bootloader to add a kernel "command-line" parameter... >>> >>> Can you give me a short Python script that effects the tweak to an ISO >>> image? I need to run the script as a regular user. >> >> It'd start by mounting it somewhere, and finish by building a new ISO >> with mkisofs, so a shell script would be more appropriate :) > > Mount? As a regular user? Let me see, how much effort are you prepared to go to in order to do this as a "regular user"... because at some point, "sudo" becomes only one of many options, including "install another Unix system somewhere that you are root of". But if you genuinely have to mount as a non-root user, there's fusermount, which is often capable of loading up an ISO. But honestly, "ssh you@somebox" can be run by anyone, so there's always a way around the whole not-having-root thing. ChrisA -- https://mail.python.org/mailman/listinfo/python-list
Re: Is shutil.get_terminal_size useless?
Chris Angelico: > On Mon, Jan 30, 2017 at 3:28 AM, Marko Rauhamaa wrote: >> Grant Edwards : >> >>> On 2017-01-29, Marko Rauhamaa wrote: I *have* been longing for a serial console in linux distros. >>> >>> Well, all it takes is a tweak to the bootloader to add a kernel >>> "command-line" parameter... >> >> Can you give me a short Python script that effects the tweak to an ISO >> image? I need to run the script as a regular user. > > It'd start by mounting it somewhere, and finish by building a new ISO > with mkisofs, so a shell script would be more appropriate :) Mount? As a regular user? Marko -- https://mail.python.org/mailman/listinfo/python-list
Re: Is shutil.get_terminal_size useless?
On Mon, Jan 30, 2017 at 3:28 AM, Marko Rauhamaawrote: > Grant Edwards : > >> On 2017-01-29, Marko Rauhamaa wrote: >>> I *have* been longing for a serial console in linux distros. >> >> Well, all it takes is a tweak to the bootloader to add a kernel >> "command-line" parameter... > > Can you give me a short Python script that effects the tweak to an ISO > image? I need to run the script as a regular user. It'd start by mounting it somewhere, and finish by building a new ISO with mkisofs, so a shell script would be more appropriate :) ChrisA -- https://mail.python.org/mailman/listinfo/python-list
Re: Is shutil.get_terminal_size useless?
Grant Edwards: > On 2017-01-29, Marko Rauhamaa wrote: >> I *have* been longing for a serial console in linux distros. > > Well, all it takes is a tweak to the bootloader to add a kernel > "command-line" parameter... Can you give me a short Python script that effects the tweak to an ISO image? I need to run the script as a regular user. Marko -- https://mail.python.org/mailman/listinfo/python-list
Re: Is shutil.get_terminal_size useless?
On 2017-01-29, Marko Rauhamaawrote: > Grant Edwards : > >> On 2017-01-28, Marko Rauhamaa wrote: >> >>> (Although if I were to design an operating system, I don't know if I >>> would bother with controlling terminals, job control or chirping >>> modems.) >> >> I've been using serial ports on Unix for 35 years, and maintaining >> serial drivers for Linux for almost 20. Many days, it seems like the >> tty/serial API in Unix is the rug under which all the ugly dirt got >> swept... >> >> [...] >> >> It's really pretty impressive how orthogonal they did manage to make >> things. > > I *have* been longing for a serial console in linux distros. Well, all it takes is a tweak to the bootloader to add a kernel "command-line" parameter... > That would make it possible to set up virtual machines from ISO > images automatically as virtualization environments can emulate a > serial interface with an SSH connection. As it stands, such > automation requires ugly, brittle VNC tricks. -- Grant -- https://mail.python.org/mailman/listinfo/python-list
Re: Is shutil.get_terminal_size useless?
Grant Edwards: > On 2017-01-28, Marko Rauhamaa wrote: > >> (Although if I were to design an operating system, I don't know if I >> would bother with controlling terminals, job control or chirping >> modems.) > > I've been using serial ports on Unix for 35 years, and maintaining > serial drivers for Linux for almost 20. Many days, it seems like the > tty/serial API in Unix is the rug under which all the ugly dirt got > swept... > > [...] > > It's really pretty impressive how orthogonal they did manage to make > things. I *have* been longing for a serial console in linux distros. That would make it possible to set up virtual machines from ISO images automatically as virtualization environments can emulate a serial interface with an SSH connection. As it stands, such automation requires ugly, brittle VNC tricks. Marko -- https://mail.python.org/mailman/listinfo/python-list
Re: Is shutil.get_terminal_size useless?
On 2017-01-28, Marko Rauhamaawrote: > (Although if I were to design an operating system, I don't know if I > would bother with controlling terminals, job control or chirping > modems.) I've been using serial ports on Unix for 35 years, and maintaining serial drivers for Linux for almost 20. Many days, it seems like the tty/serial API in Unix is the rug under which all the ugly dirt got swept... Then I think about X. and I guess the networking stuff gets ugly pretty fast when you look under the hood. It's really pretty impressive how orthogonal they did manage to make things. -- Grant -- https://mail.python.org/mailman/listinfo/python-list
Re: Is shutil.get_terminal_size useless?
Chris Angelico: > On Sun, Jan 29, 2017 at 7:04 AM, eryk sun wrote: >> Now let's get rid of the terminal via setsid: >> >>$ echo spam | >> > 2>&1 setsid python3 -c 'import os >> > fd = os.open("/dev/tty", os.O_RDONLY) >> > print(os.get_terminal_size(fd))' | >> > cat >> Traceback (most recent call last): >> File "", line 2, in >> OSError: [Errno 6] No such device or address: '/dev/tty' > > And you could have achieved the same result in any number of other > ways, too, like setting yourself up with the local boot system (true > of systemd, upstart, sysvinit, and probably of all others too), or > cron, or inetd, etc, etc, etc. You can definitely lose access to your > "controlling terminal". Eryk has a real, deeper point worth getting acquainted with. (Although if I were to design an operating system, I don't know if I would bother with controlling terminals, job control or chirping modems.) Marko -- https://mail.python.org/mailman/listinfo/python-list
Re: Is shutil.get_terminal_size useless?
On Sun, Jan 29, 2017 at 7:04 AM, eryk sunwrote: > Now let's get rid of the terminal via setsid: > >$ echo spam | > > 2>&1 setsid python3 -c 'import os > > fd = os.open("/dev/tty", os.O_RDONLY) > > print(os.get_terminal_size(fd))' | > > cat > Traceback (most recent call last): > File "", line 2, in > OSError: [Errno 6] No such device or address: '/dev/tty' And you could have achieved the same result in any number of other ways, too, like setting yourself up with the local boot system (true of systemd, upstart, sysvinit, and probably of all others too), or cron, or inetd, etc, etc, etc. You can definitely lose access to your "controlling terminal". ChrisA -- https://mail.python.org/mailman/listinfo/python-list
Re: Is shutil.get_terminal_size useless?
On Sat, Jan 28, 2017 at 5:58 PM, Chris Angelicowrote: > Processes in the middle of pipelines *do not have* terminals. No, in the following case stderr is a terminal: $ echo spam | > python3 -c 'import os > print(os.get_terminal_size(2))' | > cat os.terminal_size(columns=132, lines=43) Let's also redirect stderr to the pipe: $ echo spam | > 2>&1 python3 -c 'import os > print(os.get_terminal_size(2))' | > cat Traceback (most recent call last): File "", line 2, in OSError: [Errno 25] Inappropriate ioctl for device Now let's open and use the controlling terminal instead: $ echo spam | > 2>&1 python3 -c 'import os > fd = os.open("/dev/tty", os.O_RDONLY) > print(os.get_terminal_size(fd))' | > cat os.terminal_size(columns=132, lines=43) Now let's get rid of the terminal via setsid: $ echo spam | > 2>&1 setsid python3 -c 'import os > fd = os.open("/dev/tty", os.O_RDONLY) > print(os.get_terminal_size(fd))' | > cat Traceback (most recent call last): File "", line 2, in OSError: [Errno 6] No such device or address: '/dev/tty' -- https://mail.python.org/mailman/listinfo/python-list
Re: Is shutil.get_terminal_size useless?
Chris Angelico: > Background processes don't have terminal access. Whether it's a daemon > or something started as "commandname >/dev/null 2>/dev/null &" from bash, it doesn't have access to a terminal. A nitpick: a process running in the background or a process with no open terminal file descriptor still does have a controlling terminal under Unix/Linux. http://man7.org/linux/man-pages/man4/tty.4.html> https://docs.python.org/3/library/fcntl.html#fcntl.ioctl> https://linux.die.net/man/2/setsid> https://docs.python.org/3/library/os.html#os.setsid> Marko -- https://mail.python.org/mailman/listinfo/python-list
Re: Is shutil.get_terminal_size useless?
On Sun, Jan 29, 2017 at 3:15 AM, Steve D'Apranowrote: > On Sat, 28 Jan 2017 10:50 pm, Chris Angelico wrote: > >> On Sat, Jan 28, 2017 at 9:49 PM, Steve D'Aprano >> 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. 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. >> 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. > > 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. >> 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? Don't you see how similar this is to the pipe situation - sure, there might be a terminal that the program was invoked from, but it's utterly irrelevant to how the program actually runs. >> 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. Whether it's a daemon or something started as "commandname >/dev/null 2>/dev/null https://mail.python.org/mailman/listinfo/python-list
Re: Is shutil.get_terminal_size useless?
On 2017-01-28, Steve D'Apranowrote: > On Sat, 28 Jan 2017 10:50 pm, Chris Angelico wrote: > >> On Sat, Jan 28, 2017 at 9:49 PM, Steve D'Aprano >> 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. I'm sorry, it's not at all obvious to me (or, apparently to the author of shutil.get_terminal_size) that the output is going to end up in the terminal where you typed the command. The output might just as easily end up in a file or in a completely different terminal (possibly on a different machine). > I acknowledge that there are cases where there is no terminal. And cases where there is a different terminal entirely. To me, the current behavior of shutil.get_terminal_size seems to be the most useful. -- Grant -- https://mail.python.org/mailman/listinfo/python-list
Re: Is shutil.get_terminal_size useless?
On 01/28/2017 09:15 AM, Steve D'Aprano wrote: > Then explain why os.get_terminal_size() returns the correct answer. Basically you were asking two different questions there. shutil.get_terminal_size always asks the question of size of the terminal that the standard output file handle is connected to. Whereas, if I read this correctly, you asked os.get_terminal_size to query the size of the terminal attached to the *standard input* file handle. These are very different things. If you want to know the size of the terminal on the input side, use os.get_terminal_size(0), not shutil. By the way my comment about raising an exception a moment ago was about os.get_terminal_size(1). Apparently shutil is trying to be a convenience function and lets you specify a default size if there is no size to determine. > 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. In your specific case, the answer is to get the terminal size by querying os.get_terminal_size on standard in, since your standard out is not a tty. In most other situations the question doesn't make a lot of sense because there's no correlation between the terminal that the process is running in and the terminal the process's output is going to be piped to when a tty is not involved. For example: command1 | python3 test_gts.py | command2 In that case your process has no terminal on either end. Only command1 and command 2 do. -- https://mail.python.org/mailman/listinfo/python-list
Re: Is shutil.get_terminal_size useless?
On 01/28/2017 09:15 AM, Steve D'Aprano wrote: > Then get_terminal_size() should raise, unless you explicitly ask for a > default size. Which it does if you call it on the standard out file handle, which is the default, and for most applications, the most useful. -- https://mail.python.org/mailman/listinfo/python-list
Re: Is shutil.get_terminal_size useless?
On 01/28/2017 09:03 AM, Michael Torrie wrote: > On 01/28/2017 04:00 AM, Steve D'Aprano wrote: >>> $ COLUMNS=123 python3 test_gts.py | cat >>> shutil: os.terminal_size(columns=123, lines=999) >>> os: os.terminal_size(columns=72, lines=48) > > Interesting. On my machine with Python 3.4, calling > os.get_terminal_size() and piping the output results in the exception > OSError: [Errno 25] Inappropriate ioctl for device Oh I see you are calling get_terminal_size() on file handle 0 which is standard in. Generally, I can't think of very many use cases for caring about the terminal size on the *input* side. Most times I only care about the output side, which if it's a pipe doesn't make a lot of sense to care about, other than maximum line length. -- https://mail.python.org/mailman/listinfo/python-list
Re: Is shutil.get_terminal_size useless?
On Sat, 28 Jan 2017 10:50 pm, Chris Angelico wrote: > On Sat, Jan 28, 2017 at 9:49 PM, Steve D'Aprano >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. I acknowledge that there are cases where there is no terminal. As you say: > Likewise if you're running in some detached > (non-terminal) context, Then get_terminal_size() should raise, unless you explicitly ask for a default size. Likewise: > or if you're being run over some remote link > that hasn't transmitted terminal size info, I think that the possibility of having such a remote link is a failure of the remote protocol being used. (ssh? telnet?) But it is what it is. Perhaps there genuinely are circumstances where the terminal size exists but is unknowable -- but the example code isn't one of them. > 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. 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. > Would you expect that a process started from systemd is told about the > size of the terminal in which you ran "systemctl start servicename"? I > doubt it. I wouldn't make any assumptions at all about what systemd does. For all I know, it hard codes a size of (300, 100) into every single process because that's the size of terminals on Lennart's laptop. > 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 why should a program that's being > piped into something else automatically assume the size of the other > program's terminal? Because the other program is running in the same terminal as the first process. grep foo * | wc -l Both grep and wc are running in the same terminal. (Assuming there is any terminal at all.) > You might well be a completely background process. And if that background process is running in a terminal? What's your point? I'm not disputing that there are processes where no terminal exists at all. That's a red herring. os.get_terminal_size() returns the correct result. Why doesn't shutil? > You can still ask the concrete question about terminal size, You mean like a function called get_terminal_size()? > and that's in the 'os' module. The 'shutil' module also looks at > environment variables, Why? We already have ways to look at environment variables. The only complication here is that, perhaps, there may be more than one set of environment variables to compare, and some order that they should be preferred. It is often the Unix way that there might be two, or twenty-two *wink* different environment variables to communicate this information. But in this case, I'm not able to find anything other than the two standard variables, COLUMNS and LINES. Aside: technically these are shell variables, and they may not exist in arbitrary shells. They also need to be explicitly exported as environment variables to become visible to Python. See this StackOverflow question for more information: http://unix.stackexchange.com/questions/215584/whats-the-name-of-the-environment-variable-with-current-terminal-width -- Steve “Cheer up,” they said, “things could be worse.” So I cheered up, and sure enough, things got worse. -- https://mail.python.org/mailman/listinfo/python-list
Re: Is shutil.get_terminal_size useless?
On 01/28/2017 04:00 AM, Steve D'Aprano wrote: >> $ COLUMNS=123 python3 test_gts.py | cat >> shutil: os.terminal_size(columns=123, lines=999) >> os: os.terminal_size(columns=72, lines=48) Interesting. On my machine with Python 3.4, calling os.get_terminal_size() and piping the output results in the exception OSError: [Errno 25] Inappropriate ioctl for device Which is what I'd expect, seeing as there's no tty and no terminal emulator. I'm not sure why you're not seeing that error also. > Unless your terminal *actually is* 123 columns wide, I don't see that as an > advantage. I see that as "Hey look, we can fool shutil into returning > absolute garbage instead of the terminal size!" Influencing the column width used by a program for output is very useful and is often used in shell scripting and piping data. This allows programs to just have to use one mechanism to determine line length, regardless of whether it's running on a tty or connected to a pipe. > I can already read environment variables using os.getenv() and os.environ, > so this gives me no new functionality. Sure but working through shutils provides a uniform way of getting the maximum column width. Furthermore using shutils is probably more portable. I'm not sure if you can override LINES or not, but even if you can't that's pointless. > But what happens if you resize the terminal while the process is running? > Again, the os.get_terminal_size() correctly returns the updated size, while > shutil.get_terminal_size() doesn't. For a program that's communicating with a tty, you just have to call shutil.get_terminal_size() again to get the updated size. For your piped process, the question doesn't make sense. You can't resize a pipe. The only process that can respond to terminal changes is the final process in your chain that's actually writing to the tty. If your process is talking to a pipe, then the only thing you can do is make an arbitrary decision about the line length (columns==999 means unlimited, otherwise limit to columns). Nothing else makes sense. -- https://mail.python.org/mailman/listinfo/python-list
Re: Is shutil.get_terminal_size useless?
On 2017-01-28, Steve D'Apranowrote: > Right: I want to know what the terminal window is sized to. What do you mean by "the terminal"? Do you mean the device to which the program's output is connected? Since output is what you have control over, and what's width you might want to change, that's what makes sense to me. Or do you mean the device to which the program's input is connected? Or do you mean the controlling tty for the process group in which the program is running? > 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. Why do you want to know what the terminal width is if it isn't to control the format of the output? That's why _I_ would want to know the terminal width. And in that case, the width of there stdout is going is what makes the most sense to me. > But I'm only asking one question: what's the terminal size? The library call you're making defines "the terminal" as the device to which stdout is connected. You apparently which to define "the terminal" differently. In which case you need to use a different library call. -- Grant -- https://mail.python.org/mailman/listinfo/python-list
Re: Is shutil.get_terminal_size useless?
Steve D'Aprano wrote: >> One potential advantage of shutil.get_terminal_size() is that you can >> affect it with an environment variable: >> >> $ python3 test_gts.py | cat >> shutil: os.terminal_size(columns=999, lines=999) >> os: os.terminal_size(columns=72, lines=48) >> >> $ COLUMNS=123 python3 test_gts.py | cat >> shutil: os.terminal_size(columns=123, lines=999) >> os: os.terminal_size(columns=72, lines=48) > > Unless your terminal *actually is* 123 columns wide, I don't see that as > an advantage. But the script does not write to the terminal and has no way (?) of knowing whether the pipe ends in the terminal or in a file. Assuming it does end in the terminal seems like a good default to me, and setting COLUMNS provides a uniform way to override that default. I prefer that to what e. g. aptitude does which uses the full width of the terminal window but falls back to 80 $ aptitude search foo p bygfoot - Fußball-Managerspiel ... $ aptitude search foo | grep python p python-foolscap - RPC-System auf Basis der Objektfähigkeiten p python-rfoo - Fast RPC package for Python (and a To get back well-behaved output you need both the envvar and a commandline option: $ aptitude search -w $COLUMNS foo | grep python p python-foolscap - RPC-System auf Basis der Objektfähigk > I see that as "Hey look, we can fool shutil into returning > absolute garbage instead of the terminal size!" There are valid reasons for temporarily altering the number of columns, like writing to a file or preparing a code sample. > I can already read environment variables using os.getenv() and os.environ, > so this gives me no new functionality. shutil.get_terminal_size() combines access to shell variables and the os, and IMHO that is a useful approach. -- https://mail.python.org/mailman/listinfo/python-list
Re: Is shutil.get_terminal_size useless?
On Sat, Jan 28, 2017 at 8:03 AM, Steve D'Apranowrote: > print('shutil:', shutil.get_terminal_size(fallback=(999, 999))) > print('os:', os.get_terminal_size(0)) [snip] > But if I pipe the output to something else, the shutil version fails to > determine the correct terminal size, and falls back on the default: The high-level shutil wrapper uses sys.__stdout__, without falling back on sys.__stdin__ or sys.__stderr__, so it has to rely on the environment variables and/or fallback value when stdout isn't a terminal. OTOH, in this case you're calling os.get_terminal_size(0) on the STDIN file descriptor, which obviously works -- at least on Unix -- because it's a tty. On Windows that generally won't work because getting the screen size requires a handle for a screen buffer, not an input buffer. In this case, os.get_terminal_size(2) would generally work on Windows because stderr hasn't been redirected. I just wrote an extended version of shutil.get_terminal_size that tries six (minus two) ways to Sunday to get the terminal size, starting with /dev/tty on Unix and CONOUT$ on Windows. It's needlessly complicated by the Windows implementation of os.get_terminal_size, which is strangely hard coded. os.get_terminal_size calls GetStdHandle with a fake mapping of 0, 1, and 2 to the standard handles. It should just call get_osfhandle on the given file descriptor. That way someone could use something like the following: with open('CONOUT$', 'r+') as conout: size = os.get_terminal_size(conout.fileno()) which would be guaranteed to work if the process is attached to a console. The current implementation forces one to temporarily modify a standard handle, which has to be gated by a lock for thread safety. -- https://mail.python.org/mailman/listinfo/python-list
Re: Is shutil.get_terminal_size useless?
On Sat, Jan 28, 2017 at 9:49 PM, Steve D'Apranowrote: > 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. Likewise if you're running in some detached (non-terminal) context, or if you're being run over some remote link that hasn't transmitted terminal size info, 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. Would you expect that a process started from systemd is told about the size of the terminal in which you ran "systemctl start servicename"? I doubt it. Would you expect a cronjob to use the terminal size when you most recently edited crontab? No. So why should a program that's being piped into something else automatically assume the size of the other program's terminal? You might well be a completely background process. You can still ask the concrete question about terminal size, and that's in the 'os' module. The 'shutil' module also looks at environment variables, and probably would be the place to respond to TELNET NAWS if that has any sort of primary-level support. ChrisA -- https://mail.python.org/mailman/listinfo/python-list
Re: Is shutil.get_terminal_size useless?
On Sat, 28 Jan 2017 07:39 pm, Peter Otten wrote: > One potential advantage of shutil.get_terminal_size() is that you can > affect it with an environment variable: > > $ python3 test_gts.py | cat > shutil: os.terminal_size(columns=999, lines=999) > os: os.terminal_size(columns=72, lines=48) > > $ COLUMNS=123 python3 test_gts.py | cat > shutil: os.terminal_size(columns=123, lines=999) > os: os.terminal_size(columns=72, lines=48) Unless your terminal *actually is* 123 columns wide, I don't see that as an advantage. I see that as "Hey look, we can fool shutil into returning absolute garbage instead of the terminal size!" I can already read environment variables using os.getenv() and os.environ, so this gives me no new functionality. > I have the line > > export LINES COLUMNS > > in my .bashrc, so by default I see the physical size: > > $ export COLUMNS LINES > $ python3 test_gts.py | cat > shutil: os.terminal_size(columns=72, lines=48) > os: os.terminal_size(columns=72, lines=48) But what happens if you resize the terminal while the process is running? Again, the os.get_terminal_size() correctly returns the updated size, while shutil.get_terminal_size() doesn't. -- Steve “Cheer up,” they said, “things could be worse.” So I cheered up, and sure enough, things got worse. -- https://mail.python.org/mailman/listinfo/python-list
Re: Is shutil.get_terminal_size useless?
On Sat, 28 Jan 2017 07:27 pm, Chris Angelico wrote: > On Sat, Jan 28, 2017 at 7:03 PM, Steve D'Aprano >wrote: >> But if I pipe the output to something else, the shutil version fails to >> determine the correct terminal size, and falls back on the default: >> >> >> [steve@ando ~]$ python3.5 test_gts.py | cat >> shutil: os.terminal_size(columns=999, lines=999) >> os: os.terminal_size(columns=116, lines=29) >> >> >> while the os version gives the correct result. > > I believe the problem here is your definition of "correct". That would be the dictionary definition: Correct - conformable to truth; not faulty; free from error :-P > When you > inquire of the os module, you're asking, at a fairly low level, what > the terminal window is sized to. Right: I want to know what the terminal window is sized to. > But when you ask shutil, you're > asking what a shell utility should do. No, I'm asking what the terminal window is sized to. That's why the function is called get_terminal_size(), not what_should_a_shell_utility_do(). What should a shell utility do, under what circumstances? How can any function answer that? > Quite a few programs change in > behaviour when piped into something else (for instance, 'ls' will > often apply colour and columnate its text, but if you pipe it into > grep, you don't want any of that), Sure, and if I wanted to know if standard output was being piped to something else, I'd expect to call a function called something like where_is_std_out_being_piped_to(). 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. That would be like calling len(some_string) and expecting it to return None if some_string was all uppercase. > and shutil is acknowledging that different effect. Before there can be a *different* effect, there needs to be an *original* effect, and I have no idea what effects you are referring to. Be precise, please. I don't dispute that there are times where a process may wish to change behaviour when being piped to something else. But that's a red herring: I'm asking what the terminal size is. I expect to get the terminal size, or perhaps an exception if there is no terminal, with an *optional* default, not a mandatory one. So far it sounds like shutil.get_terminal_size() is broken by design. Can somebody convince me it isn't? > Both are correct answers - to different questions. But I'm only asking one question: what's the terminal size? It sounds like your answer is just a long, round-about way of saying "Yes, it's useless. You cannot trust it to return the terminal size, even when there is a terminal." I haven't even asked what happens if it is called when there is no associated terminal... but now I'm afraid that if I do, it will return the number of CPUs in my computer or something... -- Steve “Cheer up,” they said, “things could be worse.” So I cheered up, and sure enough, things got worse. -- https://mail.python.org/mailman/listinfo/python-list
Re: Is shutil.get_terminal_size useless?
Steve D'Aprano wrote: > shutil.get_terminal_size returns the wrong values when you pipe your > output to another process, even it you do so in a terminal. Consider this > script: > > > import os > import shutil > print('shutil:', shutil.get_terminal_size(fallback=(999, 999))) > print('os:', os.get_terminal_size(0)) > > > That uses two different methods to get the terminal size. If I run that in > a terminal in the normal way, it works fine, returning the correct size > for my terminal: > > > [steve@ando ~]$ python3.5 test_gts.py > shutil: os.terminal_size(columns=116, lines=29) > os: os.terminal_size(columns=116, lines=29) > > > But if I pipe the output to something else, the shutil version fails to > determine the correct terminal size, and falls back on the default: > > > [steve@ando ~]$ python3.5 test_gts.py | cat > shutil: os.terminal_size(columns=999, lines=999) > os: os.terminal_size(columns=116, lines=29) > > > while the os version gives the correct result. > > Is shutil.get_terminal_size useless? When, if ever, should I use it in > preference to the os version? If the shutil version is broken, can it be > fixed? One potential advantage of shutil.get_terminal_size() is that you can affect it with an environment variable: $ python3 test_gts.py | cat shutil: os.terminal_size(columns=999, lines=999) os: os.terminal_size(columns=72, lines=48) $ COLUMNS=123 python3 test_gts.py | cat shutil: os.terminal_size(columns=123, lines=999) os: os.terminal_size(columns=72, lines=48) I have the line export LINES COLUMNS in my .bashrc, so by default I see the physical size: $ export COLUMNS LINES $ python3 test_gts.py | cat shutil: os.terminal_size(columns=72, lines=48) os: os.terminal_size(columns=72, lines=48) > Thanks to Bernardas Ališauskas: > > http://granitosaurus.rocks/getting-terminal-size.html -- https://mail.python.org/mailman/listinfo/python-list
Re: Is shutil.get_terminal_size useless?
On Sat, Jan 28, 2017 at 7:03 PM, Steve D'Apranowrote: > But if I pipe the output to something else, the shutil version fails to > determine the correct terminal size, and falls back on the default: > > > [steve@ando ~]$ python3.5 test_gts.py | cat > shutil: os.terminal_size(columns=999, lines=999) > os: os.terminal_size(columns=116, lines=29) > > > while the os version gives the correct result. I believe the problem here is your definition of "correct". When you inquire of the os module, you're asking, at a fairly low level, what the terminal window is sized to. But when you ask shutil, you're asking what a shell utility should do. Quite a few programs change in behaviour when piped into something else (for instance, 'ls' will often apply colour and columnate its text, but if you pipe it into grep, you don't want any of that), and shutil is acknowledging that different effect. Both are correct answers - to different questions. ChrisA -- https://mail.python.org/mailman/listinfo/python-list
Is shutil.get_terminal_size useless?
shutil.get_terminal_size returns the wrong values when you pipe your output to another process, even it you do so in a terminal. Consider this script: import os import shutil print('shutil:', shutil.get_terminal_size(fallback=(999, 999))) print('os:', os.get_terminal_size(0)) That uses two different methods to get the terminal size. If I run that in a terminal in the normal way, it works fine, returning the correct size for my terminal: [steve@ando ~]$ python3.5 test_gts.py shutil: os.terminal_size(columns=116, lines=29) os: os.terminal_size(columns=116, lines=29) But if I pipe the output to something else, the shutil version fails to determine the correct terminal size, and falls back on the default: [steve@ando ~]$ python3.5 test_gts.py | cat shutil: os.terminal_size(columns=999, lines=999) os: os.terminal_size(columns=116, lines=29) while the os version gives the correct result. Is shutil.get_terminal_size useless? When, if ever, should I use it in preference to the os version? If the shutil version is broken, can it be fixed? Thanks to Bernardas Ališauskas: http://granitosaurus.rocks/getting-terminal-size.html -- Steve “Cheer up,” they said, “things could be worse.” So I cheered up, and sure enough, things got worse. -- https://mail.python.org/mailman/listinfo/python-list