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 ? 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 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
Sign up to request clarification or add additional context in comments.

6 Comments

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/…
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.
Is it guaranteed that __del__ will be called as soon as the object goes out of scope ? Or is it implementation dependent ?
@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.
@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...
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.