Interactive scripts (back on topic for once) [was Re: The "loop and a half"]
eryk sun
eryksun at gmail.com
Fri Oct 6 11:01:04 EDT 2017
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.
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