huang cheng
huang cheng

Reputation: 393

Python3: ValueError: I/O operation

I just want to make the print output redirect to a file. my code as below:

import sys

# define the log file that receives your log info
log_file = open("message.log", "w")
# redirect print output to log file
sys.stdout = log_file

print ("Now all print info will be written to message.log")
# any command line that you will execute
...

log_file.close()

print ("Now this will be presented on screen")

After execute the script, it comes an error:

[~/Liaohaifeng]$ python3 log.py
Traceback (most recent call last):
  File "log.py", line 14, in <module>
  print ("Now this will be presented on screen")
ValueError: I/O operation on closed file. 

why does this happen? if I update my script as below:

import sys

# make a copy of original stdout route
stdout_backup = sys.stdout
# define the log file that receives your log info
log_file = open("message.log", "w")
# redirect print output to log file
sys.stdout = log_file

print ("Now all print info will be written to message.log"
# any command line that you will execute
...

log_file.close()
# restore the output to initial pattern
sys.stdout = stdout_backup

print ("Now this will be presented on screen")

It will be OK. So, could you please kindly tell me the theory in this issue?

Upvotes: 0

Views: 65

Answers (1)

Synedraacus
Synedraacus

Reputation: 1045

As mentioned in comments, print does not print to a closed filehandle and you have closed sys.stdout, potentially breaking any prints evoked after it closed. Which may happen even without your knowledge, eg somewhere in the imported code. That's why you shouldn't fiddle with sys.* variables (or any variables you didn't create, really) unless you absolutely need to. There is a proper way to redirect print output to a file and it goes like this:

log_file = open('message.log', 'w')
print('Stuff to print in the log', file=log_file)
log_file.close()

Or even safer like this:

with open('message.log', 'w') as log_file:
    # Do stuff
    print('Stuff to print in the log', file=log_file)

The handle will automatically flush and close when the with block finishes.

Upvotes: 1

Related Questions