Results depend on the 'stdin_encoding'
Codec values which are probably dependent on location (e.g. United States) and/or encoding directive (line 2 - line after Shebang). A
one size fits all algorithm can probably be obtained after testing various locations and default encodings. I was able to detect the following on Python 3.6.5 using Windows 10 in the United States 'stdin' as:
a. Keyboard
b. Null Device
c. Redirected file (but not the file name)
d. Pipe
Function get_stdin_encoding() seems to work OK. Other functions are for reference purposes and seem to fail when 'stdin' is the NULL DEVICE.
# 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):
NOTE: The follow is NOT Python code but a Windows .bat file
@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
exit
Results 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
Added .zip file attachment containing:
a. RedirectStdin-001.bat
b. RedirectStdin-001.py