OcéF
OcéF

Reputation: 47

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.

Upvotes: 0

Views: 1851

Answers (2)

ImranD
ImranD

Reputation: 320

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()

Upvotes: 2

ImranD
ImranD

Reputation: 320

I think the issue is that you incorrectly use your sed function. You open the file you want to edit inside your main function, and then it is opened again (and then closed) inside the sed function.

It looks like your sed function is supposed to be used on an entire file, not just a line.

If you edit your main function to something like that, it should work (if not, comment what's wrong):

def main():
    """
    Replace all year-month-days which have a possible wrong pattern
    """
    occurrences = 999 # arbitray number. If you know the exact number, you may want to edit this.
    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, count=occurrences)

Upvotes: 0

Related Questions