pythonvalueerrorfclose

python: getting ValueError: I/O operation on closed file


I have an issue with my code. I am trying to replace a pattern un a file. First I have an error on the number of opening files because I forgot to close my file. But now, I had f.close() into my code and I have the following error:

ValueError: I/O operation on closed file.

Here you may find a part of my code. Someone has an idea of what is wrong ?

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import re
import shutil
from tempfile import mkstemp

infile = 'test_file.txt'
year  = int('2009')
month = int('1')
day   = int('10')

#################################################################################
def sed(pattern, replace, source):
    """
    Reads a source file and writes the destination file.
    In each line, replaces pattern with replace.
    Args:
        pattern (str): pattern to match (can be re.pattern)
        replace (str): replacement str
        source  (str): input filename
    """
    fin = open(source, 'r')
    fd, name = mkstemp()
    fout = open(name, 'w')
    for line in fin:
        out = re.sub(pattern, replace, line)
        fout.write(out)
    fin.close()
    fout.close()
    shutil.move(name, source) 

#################################################################################
def main():
    """
    Replace all year-month-days which have a possible wrong pattern
    """
    for i in range (6):
        for j in range (12):
            for k in range (22):
                Year = year + i; Month = month + j; Day = day + k
                pattern = '%s %s%s' %(Year, Month, Day)
                replace = '%s %s %s' %(Year, Month, Day)
                sed(pattern, replace, infile)

#################################################################################
if __name__ == "__main__":
    main()

###### END 

Thank you a lot.


Solution

  • I'm posting this as another answer because, well, it's clearly different.

    Since you have an issue with your sed function opening too many files, I tried writing something that opens files as few times as possible. Moreover, you said that the file you want to edit is pretty big, so I avoided reading it directly into memory.

    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    
    import re
    
    input_file = 'test_file.txt'
    output_file = 'result_file.txt'
    
    def main():
      pattern = r"(\d{4}) (\d{1,2})(\d{2})"
      replace = r"\1 \2 \3"
      with open(input_file, "r") as inp:
        with open(output_file, "w") as oup:
            for line in inp:
              sub = re.sub(pattern, replace, line)
              oup.write(sub)
    
    if __name__ == "__main__":
        main()