ntough
ntough

Reputation: 373

How to understand sys.stdout and sys.stderr in Python

I have the following simple Python code.

stdout = sys.stdout
stderr = sys.stderr

try:
   # Omitted

finally:
  sys.stdout = stdout

After searching, I found that sys.stdin, sys.stdout, and sys.stderr are file objects corresponding to the interpreter's standard input, standard output and standard error streams. So, my guess here is that we first assign the sys.stdout and sys.stderr to the variables stdout and stderr.

Then, even if there are exceptions in the try statement, can we always get the sys.stdout back? Is this correct? I felt that I was still confused.

Upvotes: 13

Views: 57944

Answers (2)

MozVi
MozVi

Reputation: 1

About the link you sent for the logging module, it seems to be deprecated (which is almost guaranteed after more than 8 years). Here should (hopefully) be the right link for the logging module.

Upvotes: 0

brenns10
brenns10

Reputation: 3379

In normal C programs, there are three "files" open by default: stdin, stdout, and stderr. When you do input and output in C, by default they come from stdin and stdout. But, you can also use them where code expects files, or reassign them to be new files.

Python seeks to "mimic" this behavior of C. When you print() in Python, your text is written to Python's sys.stdout. When you do input(), it comes from sys.stdin. Exceptions are written to sys.stderr.

You can reassign these variables in order to redirect the output of your code to a file other than stdout. This is very similar to shell redirection, if you're familiar with that. The reason you might do something like this is to keep a log of your program's output or make code "shut up", i.e. not send output to stdout. So, in your example example:

stdout = sys.stdout

try:
    sys.stdout = open('file.txt', 'w')
    print('blah')
    # etc
finally:
    sys.stdout.close()  # close file.txt
    sys.stdout = stdout
    sys.stderr = stderr

This code wouldn't print anything to the console, but it would write "blah" to a text file named file.txt. To make this sort of thing less error-prone, Python provides sys.__stdin__ and sys.__stdout__, which always hold the original values of sys.stdin and sys.stdout. The above code could be made simpler using this:

try:
    sys.stdout = open('file.txt', 'w')
    print('blah')
    # etc
finally:
    sys.stdout.close()  # close file.txt
    sys.stdout = sys.__stdout__

The reason Python has both stdout and __stdout__ is mainly for convenience, so you don't have to make a variable to back up stdout.

However, I have to recommend that you don't make a habit out of reassigning stdout. It's pretty easy to mess things up that way! If you want to save your code's output, you can use shell redirection. If you want to have the ability to keep a log of what your program is doing, see Python's logging module. If you want your code to be quieter, give your functions a quiet=False parameter so you can shut them up when you want! There is rarely a "genuine" need to do reassign stdout, etc. Python allows you to do it, because Python gives programmers a lot of control, and expects them to be responsible. You could do something like this, if you really wanted to:

>>> import random
>>> random.random = lambda: 1
>>> random.random()
1
>>> random.random()
1

Upvotes: 34

Related Questions