[Tutor] fileobject.close() question

Corran Webster cwebster@nevada.edu
Wed, 12 Apr 2000 16:23:23 -0700

> This has to do with buffer flushing, to be honest I'm not sure how to set
> autoflushing with python (perl would be $| = 1;),

file = open("filename", "w", 0)

The third (and optional) parameter is the buffer size; 0 means unbuffered.

You can also flush the file explicitly at any time with


> but anyway, the buffer
> waits to be filled before it writes and it flushes on a close.  If you
> don't write enough to fill the buffer, and the program exits, the buffer is
> cleaned up before the close occurs, therefore the remaining bytes are lost.
> Not closing a file handle is not a big deal with reads (at all), but I'd
> be careful with writes.

This is partially correct - while the original problem was caused in part
by the  buffer not having been written to the disk yet, Python file objects
automatically call their close() methods when they are garbage collected
(ie. at a random time, but surely before Python shuts itself down).

So you do not need to worry about buffers not being flushed unless Python
crashes (and if this is a problem, even an explicit close() may not help
you if Python never reaches it).  For long-running programs you will always
want to explicitly close() files, particularly if there could be circular
references floating around which will prevent timely garbage collection of
your file.

On to the original question:

> Subject: [Tutor] fileobject.close() question
> Author:  Tim Condit <timc@ans.net> at smtplink
> Date:    4/12/00 6:38 PM
> Greetings,
> I'm wondering about something Pythonic. The first time I ran the little
> code snip below, I left the 'fileobject.close()' function out. Basically,
> I forgot it, but at the same time, in the Quick Python book, pg. 132,
> section 13.2, curiously enough, it says:
>         "In small scripts, not closing a file object will generally
>         not have much of an effect.."

Notice the "scripts" above.

> I'm seeing something different. Before I caught my oversight, I ran this
> same little snip twice.. the first time to create the file, and the second
> time to trigger the else: statement. The file was created, but nothing was
> written to it, until I went back and added fileobject.close(). Does anyone
> know what is causing this to happen?
> Thanks,
> Tim
> FYI: the third line (testfile = ...) is all on one line)
> >>> dir()
> ['__builtins__', '__doc__', '__name__']
> >>> import os
> >>> testfile = os.path.join('/', 'afs', 'ans.net', 'user', 'timc',
> 'testfile')
> >>> if not os.path.isfile(testfile):
> ..     fileobject = open(testfile, 'w')
> ..     fileobject.write("hi there.")
> ..     fileobject.close()
> .. else:
> ..     print "Sorry, that file already exists."
> ..
> >>>

It looks like you're running this from the interactive prompt.  If this is
the case, I suspect that what happened was:

  - You ran it the first time from the interactive prompt.  This opened the
    file, but because the data was smaller than the buffer, it wasn't flushed
    and so nothing had yet been written to disk.  Also, since you did not
    explicitly close(), your file is still open, and fileobject references
    it, so it will not be garbage collected.

  - you ran it a second time from the command line (without exiting the
    interpreter, so fileobject still exists).  Because the data still had
    not been written, the file doesn't exist yet on the disk, and it doesn't
    work as you expect.

  - when you add the close(), it explicitly closes the file, which flushes the
    data and creates the file in the filesystem; and so the second time you
    run it, all is well.

However, if you had put exactly the original code:

import os
testfile = os.path.join('/', 'afs', 'ans.net', 'user', 'timc', 'testfile')
if not os.path.isfile(testfile):
    fileobject = open(testfile, 'w')
    fileobject.write("hi there.")
    print "Sorry, that file already exists."

into it's own little script and run it twice via:

python myfile.py

it would have worked perfectly without the explicit close.  This is the
behaviour that the comment in Quick Python is referring to.