# Python Concepts/Console Output
## Objective

* This lesson on Console I/O contains material specific to Python running directly from a Unix/Linux shell. It does not apply to Python running under Windows or under popular IDEs such as IDLE or PyCharm. Many of the examples will fail in various ways under Windows or with IDEs.

## Lesson

* 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 keyboard. The visual display provides console output
* and the keyboard provides "console input."
* The simplest way to write to the console or visual display is python's print function.
* $ cat t4.py
* print ('Hello, world!') # Contents of python script t4.py
* $ python3.6 t4.py # Execute the python script.
* Hello, world!
* When the print statement in the script was executed, the string 'Hello, world!' appeared on the
* visual display in front of us. In technical terms the string was written to standard output, usually the console.
* Python reserves two file objects for console output: standard output and standard error:
* >>> import sys
* >>> sys.stdout
* <_io.TextIOWrapper name='<stdout>' mode='w' encoding='UTF-8'>
* >>> sys.stderr
* <_io.TextIOWrapper name='<stderr>' mode='w' encoding='UTF-8'>
* >>> import io
* >>> isinstance(sys.stdout, io.TextIOWrapper)
* True
* >>> isinstance(sys.stderr, io.TextIOWrapper)
* True
* Both of the above file objects are always open for writing in text mode.
* Each of the file objects has its associated file descriptor:
* >>> sys.stdout.fileno
* 1
* >>> sys.stderr.fileno
* 2
* File descriptor 1 usually means standard output, file descriptor 2 usually means standard error.
* When you write to stdout or stderr, the data written usually appears on the visual display in front of you
* unless their outputs are redirected.

## Writing to standard output

* $ cat t4.py
* import sys
* import os
* print ('line 1 to stdout ')
* sys.stdout.write('line 2 to stdout ')
* os.write(1, b'line 3 to stdout ')
* $ python3.6 t4.py
* line 1 to stdout
* line 3 to stdout line 2 to stdout $
* Line 3 was printed before line 2. To produce the expected result flush the buffer as necessary.
* import sys
* import os
* print ('line 1 to stdout ')
* sys.stdout.write('line 2 to stdout ') ; sys.stdout.flush
* os.write(1, b'line 3 to stdout ')
* $ python3.6 t4.py
* line 1 to stdout
* line 2 to stdout line 3 to stdout $
* To produce acceptable output add the newline at the end of each line as necessary:
* import sys
* import os
* print ('line 1 to stdout ')
* sys.stdout.write('line 2 to stdout \n') ; sys.stdout.flush
* os.write(1, b'line 3 to stdout \n')
* $ python3.6 t4.py
* line 1 to stdout
* line 2 to stdout
* line 3 to stdout

## Writing to standard error

* import sys
* import os
* print (' line 1e to stderr ', file=sys.stderr)
* sys.stderr.write(' line 2e to stderr \n') ; sys.stderr.flush
* os.write(2, b' line 3e to stderr \n')
* $ python3.6 t4.py
* line 1e to stderr
* line 2e to stderr
* line 3e to stderr
* $ python3.6 t4.py 2>/dev/null # Standard error redirected.
* $ # No output to console.

## Output streams redirected

* import sys
* import os
* print (' line 1 to stdout ')
* sys.stdout.write(' line 2 to stdout \n') ; sys.stdout.flush
* os.write(1, b' line 3 to stdout \n')
* print (' line 1e to stderr ', file=sys.stderr)
* sys.stderr.write(' line 2e to stderr \n') ; sys.stderr.flush
* os.write(2, b' line 3e to stderr \n')
* $ python3.6 t4.py # No output redirection
* line 1 to stdout # All output appears on the console.
* line 2 to stdout
* line 3 to stdout
* line 1e to stderr
* line 2e to stderr
* line 3e to stderr
* $ python3.6 t4.py 1>/dev/null # stdout redirected
* line 1e to stderr # Only stderr appears on console.
* line 2e to stderr
* line 3e to stderr
* $ python3.6 t4.py 2>/dev/null # stderr redirected
* line 1 to stdout # Only stdout appears on console.
* line 2 to stdout
* line 3 to stdout
* $ python3.6 t4.py 1>/dev/null 2>/dev/null # Both streams redirected.
* $ # No output to console.
* $ python3.6 t4.py >/dev/null # If no fd is specified, default is 1.
* line 1e to stderr
* line 2e to stderr
* line 3e to stderr

## Overriding output redirection

* If you wish to override output redirection so that some output goes to the terminal unconditionally, here is one way to do it:
* import sys
* import os
* print ('hello, world!') # file=sys.stdout is default
* print ('Hello, World!', file=sys.stderr)
* print ('Name of my terminal is:', os.ttyname(0))
* f = open(os.ttyname(0), 'wt')
* print ('File object opened for output to my terminal is:', f)
* print ('line 1 written to terminal', file=f)
* f.close
* $ python3.6 t5.py # No output redirection.
* hello, world!
* Hello, World!
* Name of my terminal is: /dev/ttys003
* File object opened for output to my terminal is: <_io.TextIOWrapper name='/dev/ttys003' mode='wt' encoding='UTF-8'>
* line 1 written to terminal
* $ python3.6 t5.py >sout 2>serr # File descriptors 1 and 2 redirected
* line 1 written to terminal # This output was not redirected.
* $ cat sout
* hello, world!
* Name of my terminal is: /dev/ttys003
* File object opened for output to my terminal is: <_io.TextIOWrapper name='/dev/ttys003' mode='wt' encoding='UTF-8'>
* $ cat serr
* Hello, World!
* The above code makes the following assumption:
* >>> os.ttyname(0) == os.ttyname(1) == os.ttyname(2)
* True
* If the above assumption is not valid:
* >>> f1 = open(os.ttyname(1), 'wt') ; f1 # Device associated with stdout.
* <_io.TextIOWrapper name='/dev/ttys002' mode='wt' encoding='UTF-8'>
* >>> f2 = open(os.ttyname(2), 'wt') ; f2 # Device associated with stderr.
* <_io.TextIOWrapper name='/dev/ttys002' mode='wt' encoding='UTF-8'>

## Further Reading or Review

* Previous Lesson: Other statements
* This Lesson:Console Output
* Next Lesson: Console Input
* Course Home Page