Python Concepts/Console Input
Objective
edit
|
Lesson
edit
In the context of this lesson, the word "console" implies the visual display which you see in front of you when you sit at your desk, and also the attached keyboard. The keyboard provides "console input" while the visual display provides console output. Other input devices such as mice, joysticks, game controllers and touch screens are not covered in this lesson. Python reserves one file object for console input, standard input: >>> import io
>>> import sys
>>>
>>> sys.stdin
<_io.TextIOWrapper name='<stdin>' mode='r' encoding='UTF-8'>
>>> isinstance(sys.stdin, io.TextIOWrapper)
True
>>>
The above file object is always open for reading in text mode. It has its associated file descriptor: >>> sys.stdin.fileno()
0
>>>
More information about sys.stdin: >>> sys.stdin.isatty()
True # When input is keyboard.
>>> sys.stdin.closed
False
>>> sys.stdin.readable()
True
>>> sys.stdin.seekable()
True
>>> sys.stdin.tell()
5296
>>> sys.stdin.encoding
'UTF-8'
>>>
>>> os.device_encoding(0)
'UTF-8'
>>> os.isatty(0)
True
>>> os.ttyname(0)
'/dev/ttys001'
>>> os.get_terminal_size(0)
os.terminal_size(columns=122, lines=47)
>>> >>> os.get_terminal_size(0)
os.terminal_size(columns=115, lines=42) # You can change the size of your terminal window.
>>> os.stat(0)
os.stat_result(st_mode=8592, st_ino=697, st_dev=202182376, st_nlink=1, st_uid=501, st_gid=4, st_size=0, ....)
>>>
Because |
Reading from stdin
edit
File descriptor 0 usually means standard input. When your python script reads from standard input, this usually means that it is reading data which you are typing on your keyboard. Because file descriptor 0 reads text, the new line character at the end of each line becomes significant. >>> a = sys.stdin.readline() # The readline method waits until you type '\n'.
The quick, brown fox ...
>>> a
'The quick, brown fox ...\n'
>>>
>>> a = sys.stdin.read(5)
ABCD EFGH # You entered 10 characters.
>>> a
'ABCD ' # a contains 5 characters. The remaining characters are waiting to be read.
>>> b = sys.stdin.read(5)
>>> b
'EFGH\n' # All input has been read.
>>>
>>> a = sys.stdin.read(5) # Read 5 characters from stdin.
ABCD EFGH IJKL # You entered 15.
>>> a
'ABCD '
>>> b = sys.stdin.readline() # There are still 10 characters waiting to be read.
>>> b
'EFGH IJKL\n' # b contains all remaining characters.
>>>
In the real world your python script will probably read from stdin after supplying a prompt for your response. import sys
import os
print ('Enter date-of-birth [mm/dd/yyyy]: ', end='', flush=True)
a = sys.stdin.readline()
print ('You entered', a, end='') # str a has '\n' at end.
$ python3.6 t4.py Enter date-of-birth [mm/dd/yyyy]: 12/31/1967 You entered 12/31/1967 $ python's built-in function import sys
import readline
s = input ('Enter date-of-birth [mm/dd/yyyy]: ')
print ('You entered', s)
$ python3.6 t4.py Enter date-of-birth [mm/dd/yyyy]: 12/31/1967 You entered 12/31/1967 $ If the readline module was loaded, then input() will use it to provide elaborate line editing and history features similar to command line editing with emacs. |
Detecting timeout on stdin
edit
The python script above sends a prompt to stdout and expects a response on stdin. What should happen if the person at the keyboard is called away and no response is forthcoming? You decide to terminate the session after 30 seconds of inactivity. Here is one way to do it: $ cat t6.py import signal
import sys
import readline
def handler(signum, frame):
print ('\nOperation timed out.')
exit (99)
# Set the signal handler and a 30-second alarm
signal.signal(signal.SIGALRM, handler)
signal.alarm(30)
status = 0
try :
s = input ('Enter date-of-birth [mm/dd/yyyy]: ')
except KeyboardInterrupt :
print ('\nKeyboardInterrupt detected.' )
status = 98
except SystemExit :
print ('SystemExit detected.' )
status = 97
except :
print ('\nException detected: ', str(sys.exc_info()[0]) )
status = 96
else :
print ('You entered', s)
signal.alarm(0) # Disable the alarm.
exit (status)
$ python3.6 t6.py ; echo $? Enter date-of-birth [mm/dd/yyyy]: 12/31/1999 # Normal input. You entered 12/31/1999 0 # Normal exit 0. $ $ python3.6 t6.py ; echo $? Enter date-of-birth [mm/dd/yyyy]: # No input. Operation timed out. SystemExit detected. 97 # Exit with error status 97. $ $ python3.6 t6.py ; echo $? Enter date-of-birth [mm/dd/yyyy]: # Entered ^C. KeyboardInterrupt detected. 98 # Exit with error status 98. $
|
Input stream redirected
edit
Usually $ cat t4.py import sys
import readline
print ('sys.stdin.isatty():', sys.stdin.isatty())
s = input ('Enter date-of-birth [mm/dd/yyyy]: ')
if not sys.stdin.isatty() :
print ()
print ('You entered', s)
$ python3.6 t4.py sys.stdin.isatty(): True # This is interactive session. Enter date-of-birth [mm/dd/yyyy]: 12/31/1967 # Input from keyboard. You entered 12/31/1967 $ $ echo '12/31/1988' | python3.6 t4.py # Input from a pipe. sys.stdin.isatty(): False # Not interactive. Enter date-of-birth [mm/dd/yyyy]: # No input from keyboard. You entered 12/31/1988 $
|
Console input from terminal
edit
The terminal can provide console input. On Unix the device name of the terminal is available and it behaves like a file: $ cat t5.py import os
print ('Name of my terminal is:', os.ttyname(0))
f = open(os.ttyname(0)) # for reading
print ('File object opened for reading from my terminal is:', f)
print ('Enter name of your favorite pet: ', end='',flush=True)
pet = f.read()
f.close()
print ('Input from terminal was:', pet, end='')
print ('len(pet) =', len(pet))
$ python3.6 t5.py Name of my terminal is: /dev/ttys003 File object opened for reading from my terminal is: <_io.TextIOWrapper name='/dev/ttys003' mode='r' encoding='UTF-8'> Enter name of your favorite pet: Fido # Enter 'Fido\n' then ^D for end-of-file. Input from terminal was: Fido len(pet) = 5 # String pet contains 5 characters (including the new-line) and without the ^D. $
|
Assignments
edit
|
Further Reading or Review
edit
|
References
edit
1. Python's documentation: 29.1. sys — System-specific parameters and functions: "sys.stdin" "16.1.4. File Descriptor Operations," "18.8.3. Example (of signal.alarm(....))"
"16.2.3.1. I/O Base Classes," "16.2.3.4. Text I/O"
"os.get_terminal_size(fd=STDOUT_FILENO)," "input(....)," "print(*objects, ....)"
|