May-28-2018, 03:34 AM
how to detect if sys.stdin is the controlling tty (as opposed to a pipe, or a socket, or a file, or "/dev/null", or some other tty the script was invoked to read from)? is there an equivalent in windows?
# Tested using Python 3.6.5 on Windows 10 # # Reference: https://python-forum.io/Thread-detect-if-sys-stdin-is # Reference: https://stackoverflow.com/questions/323829/how-to-find-out-if-there-is-data-to-be-read-from-stdin-on-windows-in-python # Reference: https://stackoverflow.com/questions/13442574/how-do-i-determine-if-sys-stdin-is-redirected-from-a-file-vs-piped-from-another # Reference: https://docs.python.org/3/library/os.html # NOTE: os.ttyname(sys.stdin.fileno()) is NOT available on Windows # Reference: https://docs.python.org/3/library/codecs.html (Codec values in section 7.2.3 Standard Encodings) ################################## ################################## #NOTE: The only method that seems to work on Windows is get_stdin_encoding(). # The other methods FAIL when stdin is the NULL DEVICE ################################## ################################## import os import stat import sys def is_stdin_keyboard(): #NOTE: This returns INCORRECT results when 'stdin' is the NULL DEVICE return os.isatty( sys.stdin.fileno()) def get_stdin_from_stat(): #NOTE: this function is NOT USED - incorporated into get_stdin_encoding() mode = os.fstat(0).st_mode if stat.S_ISFIFO(mode): return 'Pipe' elif stat.S_ISREG(mode): return 'Redirected' else: return 'Keyboard' def get_stdin_encoding(): # NOTE: Results depend on the 'stdin_encoding' values which are probably dependent # on location (e.g. United States) and/or encoding directive (line 2 - line after Shebang). # See https://docs.python.org/3/library/codecs.html (Codec values in section 7.2.3 Standard Encodings) stdin_encoding = getattr(sys, 'stdin').encoding if stdin_encoding == 'cp437': stdin_source = 'Null Device' elif stdin_encoding == 'cp1252': #return 'file or pipe' mode = os.fstat(0).st_mode if stat.S_ISFIFO(mode): stdin_source = 'Pipe' else: stdin_source = 'Redirected' elif stdin_encoding == 'utf-8': stdin_source = 'Keyboard' else: stdin_source = 'Encoding=' + stdin_encoding return stdin_source + " (" + stdin_encoding + ")" print("get_stdin_encoding() results: Stdin device type is: {}.".format(get_stdin_encoding())) if is_stdin_keyboard(): print("is_stdin_keyboard() results: Stdin is the Keyboard") else: print("is_stdin_keyboard() results: Stdin is NOT the Keyboard") print("sys.stdin.isatty() results: {}".format(sys.stdin.isatty()))The following Windows cmd.exe script was used to test the code (e.g. file abc.bat):
@echo off echo Testing stdin >ScratchStdOut.txt echo. >>ScratchStdOut.txt echo ###################### >>ScratchStdOut.txt echo Testing 'Keyboard' stdin >>ScratchStdOut.txt python redirectStdin-001.py >>ScratchStdOut.txt echo ###################### >>ScratchStdOut.txt echo Testing 'Null Device' stdin >>ScratchStdOut.txt python redirectStdin-001.py >>ScratchStdOut.txt <nul echo ###################### >>ScratchStdOut.txt rem NOTE: Windows prevents this from running if the redirected 'stdin' file DOES NOT EXIST rem This creates and deletes file 'Scratch00.txt' echo Testing 'Redirected' File stdin >>ScratchStdOut.txt echo Hello >Scratch00.txt python redirectStdin-001.py >>ScratchStdOut.txt <Scratch00.txt if exist Scratch00.txt del Scratch00.txt echo ###################### >>ScratchStdOut.txt echo Testing 'Pipe' stdin >>ScratchStdOut.txt echo hello | python redirectStdin-001.py >>ScratchStdOut.txt echo ###################### >>ScratchStdOut.txt type ScratchStdOut.txt pause exitResults using the .bat file:
Output:Testing stdin
######################
Testing 'Keyboard' stdin
get_stdin_encoding() results: Stdin device type is: Keyboard (utf-8).
is_stdin_keyboard() results: Stdin is the Keyboard
sys.stdin.isatty() results: True
######################
Testing 'Null Device' stdin
get_stdin_encoding() results: Stdin device type is: Null Device (cp437).
is_stdin_keyboard() results: Stdin is the Keyboard
sys.stdin.isatty() results: True
######################
Testing 'Redirected' File stdin
get_stdin_encoding() results: Stdin device type is: Redirected (cp1252).
is_stdin_keyboard() results: Stdin is NOT the Keyboard
sys.stdin.isatty() results: False
######################
Testing 'Pipe' stdin
get_stdin_encoding() results: Stdin device type is: Pipe (cp1252).
is_stdin_keyboard() results: Stdin is NOT the Keyboard
sys.stdin.isatty() results: False
######################
Lewis# Tested using Python 3.6.5 on Windows 10 in the United States # # Reference: https://python-forum.io/Thread-detect-if-sys-stdin-is import sys if sys.stdin.isatty(): print ("Do Nothing - stdin is either 'tty' or 'null device'.") else: print ("Process 'stdin' from 'pipe' or from 'file redirection'.") for i, dataline in enumerate(sys.stdin, start=1): print(i, dataline)The following Windows cmd.exe script was used to test the code (e.g. file abc.bat):
@echo off echo Testing stdin >ScratchStdOut.txt echo. >>ScratchStdOut.txt echo ###################### >>ScratchStdOut.txt echo Testing 'Keyboard' stdin >>ScratchStdOut.txt python redirectStdin-002.py >>ScratchStdOut.txt echo ###################### >>ScratchStdOut.txt echo Testing 'Null Device' stdin >>ScratchStdOut.txt python redirectStdin-002.py >>ScratchStdOut.txt <nul echo ###################### >>ScratchStdOut.txt rem NOTE: Windows prevents this from running if the redirected 'stdin' file DOES NOT EXIST rem This creates and deletes file 'Scratch00.txt' echo Testing 'Redirected' File stdin >>ScratchStdOut.txt echo Hello >Scratch00.txt echo World >>Scratch00.txt python redirectStdin-002.py >>ScratchStdOut.txt <Scratch00.txt if exist Scratch00.txt del Scratch00.txt echo ###################### >>ScratchStdOut.txt echo Testing 'Pipe' stdin >>ScratchStdOut.txt echo Pipe stdin text - Hello World | python redirectStdin-002.py >>ScratchStdOut.txt echo ###################### >>ScratchStdOut.txt type ScratchStdOut.txt pause exitResults using the .bat file:
Output:Testing stdin
######################
Testing 'Keyboard' stdin
Do Nothing - stdin is either 'tty' or 'null device'.
######################
Testing 'Null Device' stdin
Do Nothing - stdin is either 'tty' or 'null device'.
######################
Testing 'Redirected' File stdin
Process 'stdin' from 'pipe' or from 'file redirection'.
1 Hello
2 World
######################
Testing 'Pipe' stdin
Process 'stdin' from 'pipe' or from 'file redirection'.
1 Pipe stdin text - Hello World
######################
See the .zip file attachment containing:program < /dev/tty
vs. program
.