Interactive scripts (back on topic for once) [was Re: The "loop and a half"]

Thomas Jollans tjol at tjol.eu
Fri Oct 6 11:27:06 EDT 2017


On 2017-10-06 17:01, eryk sun wrote:
> On Fri, Oct 6, 2017 at 1:31 PM, Thomas Jollans <tjol at tjol.eu> wrote:
>> On 2017-10-06 12:33, Ben Bacarisse wrote:
>>
>>> A general solution to the (rather odd) complaint about silent waiting
>>> should really check any input fileno to see if a prompt is needed.  You
>>> could argue, though, that anyone who's re-arranged a program's input so
>>> that some non-zero input fileno is attached to a terminal won't need the
>>> prompt!
>>
>> stdin is ALWAYS fileno 0, whether the input is attached to a tty or not.
>> The only situation where sys.stdin.fileno() != 0 is when sys.stdin has
>> been reassigned from within python.
>>
>> $ python -c 'import sys; print(sys.stdin.fileno())' < /dev/zero
>> 0
>>
>> This should be true for all platforms, or at least all platforms python
>> supports.
> 
> POSIX defines STDIN_FILENO as 0, and the Windows C runtime reserves FD
> 0 to map to the native StandardInput handle. But as I noted in a
> previous message, on Windows isatty(0) returns true if a process isn't
> executed with a valid StandardInput. In this case sys.stdin will be
> None, so call sys.stdin.fileno() and handle the exception if that
> fails.

Seriously? sys.stdin can be None? That's terrifying.


> 
> If you really need to know that stdin is interactive for something
> critical, then isatty() is the wrong function on Windows. You need to
> check for a console, which is most easily done by using ctypes to call
> GetConsoleMode. For example:
> 
>     import os
> 
>     if os.name == 'posix':
>         from os import isatty
> 
>     elif os.name == 'nt':
>         import ctypes
>         import msvcrt
>         kernel32 = ctypes.WinDLL('kernel32', use_last_error=True)
> 
>         def isatty(fd):
>             """Return True if the fd is connected to a console."""
>             try:
>                 handle = ctypes.c_void_p(msvcrt.get_osfhandle(fd))
>             except (OSError, IOError):
>                 return False
>             mode = ctypes.c_ulong()
>             success = kernel32.GetConsoleMode(handle, ctypes.byref(mode))
>             return bool(success)
> 





More information about the Python-list mailing list