Home > Blockchain >  Python "ValueError: I/O operation on closed file" for a text file. But opened
Python "ValueError: I/O operation on closed file" for a text file. But opened

Time:11-26

I needed to a library specific output and, so I tired it like this way. But I got "ValueError: I/O operation on closed file." Error.

Here the code example that I tried...

import sys

def print_test():
    print("Printing testing print...!")
    print("line 01")
    print("line 02")
    print("line 03")


print("Before capture")

def main():
    sys.stdout= open("test.txt", 'w')
    print_test()
    sys.stdout.close()
main()

print("After capture")

with open('test.txt', 'r') as f:
    lines= f.readlines()
    for i in lines:
        print(i)

        if "line 01" in lines:
            print("Found line 01")

CodePudding user response:

I did not know this, but after doing sys.stdout.close() it seems you cannot open other files.

However there is a better way to print in a file using print anyway, as the print function accept a file parameter. You can then do something like :

def print_test(f):
    print("Printing testing print...!", file=f)
    print("line 01", file=f)
    print("line 02", file=f)
    print("line 03", file=f)


print("Before capture")

def main():
    f = open("test.txt", 'w')
    print_test(f)
    f.close()
main()

CodePudding user response:

The error is caused by this line:

sys.stdout.close()

Effectively you are closing the stdout stream for all following print calls in your program, if you omit to pass a file object to the file parameter. See definition of print's file keyword argument:

The file argument must be an object with a write(string) method; if it is not present or None, sys.stdout will be used.

After main is finished all following print calls try accessing the re-assigned sys.stdout which now is closed. Thus giving you a ValueError.

Create a local copy of sys.stdout that you can re-assign after your call to print_test to circumvent this:

def main():
    stdout = sys.stdout  # create local copy of stdout
    sys.stdout = open("test.txt", 'w')  # change stdout
    print_test()
    sys.stdout.close()
    sys.stdout = stdout  # reassign standard output stream to sys.stdout

The other way would be to pass the file object directly to print using the file keyword

myoutput = open("test.txt", "w")
print("Print to file", file=myoutput)

# pass file object to function
def my_print(file):
    print("function call to print", file=file)
  • Related