5

I want to write a class that is able to write an html file. I now have the following skeleton:

class ColorWheel(object):
    def __init__(self, params):
        self.params = params

    def __enter__(self):
        self.f = open('color_wheel.html', 'w')
        self._write_header()
        return self

    def __exit__(self, type_unused, value_unused, traceback_unused):
        self._write_footer()
        self.f.close()

    def wheel(self):
        # Code here to write the body of the html file
        self.f.write('BODY HERE')

I use this class with:

with ColorWheel(params) as cw:
    cw.wheel()

The file is exactly written as I expect it to be. However, when I run this, I get the following error:

Exception ValueError: 'I/O operation on closed file' in <bound method ColorWheel.__del__ of ColorWheel.ColorWheel object at 0x0456A330>> ignored

I assume it is trying to close the file while it has already been closed. Is this correct? If so, what would be the proper way to close the file?

4
  • You also have a __del__ method, don't you. Commented Aug 31, 2014 at 9:34
  • do you have a for outside the with ?
    – Mazdak
    Commented Aug 31, 2014 at 9:36
  • 1
    @Kasra: what has that got to do with anything? Commented Aug 31, 2014 at 9:36
  • i seen this error when open a file with and then dont write the other part of the code inside with
    – Mazdak
    Commented Aug 31, 2014 at 9:39

1 Answer 1

7

You also have a __del__ method trying to write to the file after closing it. When cw goes out of scope and is cleaned up, the __del__ hook is called and you appear to try and write to the file at that point.

You can test if a file is closed already with:

if not self.f.closed:
    # do something with file
6
  • 1
    The answer is correct. I want to add a reference to the official documentation that you should read in order to understand the with statement: docs.python.org/3.4/reference/… Commented Aug 31, 2014 at 9:39
  • I thought I did not have a del method, but it turns out I do, since I inherited from another class. I didn't show that above, I thought it would be irrelevant. It all makes sense now. Commented Aug 31, 2014 at 9:39
  • Is it guaranteed that __del__ will be called as soon as the object goes out of scope ? Or is it implementation dependent ? Commented Aug 31, 2014 at 10:17
  • @Sylvain: that's dependent on the implementation. CPython uses reference counting and there the __del__ is called instantly. But IronPython and Jython use a garbage collection scheme and the call will be delayed. Commented Aug 31, 2014 at 10:51
  • @Martijn Concerning Jython: as the JVM does not guaranteed finalize() to even be called on program termination, does that imply __del__ might not be even be called too? I can't find a clear answer for recent version of Jython by googling around... Commented Aug 31, 2014 at 11:03

Not the answer you're looking for? Browse other questions tagged or ask your own question.