[Tutor] Re: Text processing with files

Gonçalo Rodrigues op73418 at mail.telepac.pt
Mon Oct 27 05:01:52 EST 2003


On Sun, 26 Oct 2003 10:48:10 -0800 (PST), Daniel Ehrenberg wrote:

>
>So would this be better?
>
>filepath = raw_input("Convert which file? ")
>filetext = file(filepath, "rU").read()
>file(filepath, "w").write(filetext)
>

Just a note: files are external resources, so it is a good programming
habit of disposing them explicitely.

A very common and pythonic pattern of dealing with external and
limited resources is

<open resource for use>
try:
    <use resource>
finally:
    <close resource>

In the case of files, this becomes

path = raw_input("Which file to open?")
#Open file.
f = file(path, "rU")
try:
    #Read file.
    text = f.read()
finally:
    #Close file.
    f.close()

The magic is the try/finally block. When Python encounters this, it
will execute the try block and then if no exceptions have been raised
the finally block is executed and everything goes on as normal. OTOH
if teh try block raises an exception, the finally block is executed
and only after is the exception raised. What this guarantees is that
the finally block is *always* executed - which is exactly what you
need when freeing resources (closing files, closing database
connections, releasing locks, etc.)

Now in your case, you only want to write to the file *if* the read
operation went fine, so a *robust* version goes like this:

path = raw_input("Which file to open?")
#Open file.
try:
    f = file(path, "rU")
    try:
        #Read file.
        text = f.read()
    finally:
        #Close file.
        f.close()
except:
    #Reraise exception => an error has ocurred.
    raise
else:
    #Open file for writing.
    f = file(path, "w")
    try:
        #Write to file.
        f.write(text)
    finally:
        #Close file.
        f.close()

Admittedly, the above is a little hairy, but it stays as a good
exercise in using exceptions and try/finally blocks to write robust
code.

A final note on your code:

>filetext = file(filepath, "rU").read()
>file(filepath, "w").write(filetext)

In going from the reading to the writing you are assuming that Python
closes the file in between. And you assum right, because Python makes
sure that when a file is garbage collected is closed. And that is what
happens above since by the time you get to the writing statement there
are no references to the file, so it is garbage collected, etc... BUT,
and this is a big but (only one t), this is an *implementation
detail*. It happens in the current CPython implementation but it is
not guaranteed to happen in future implementations. It is *not* true
in the Jython implementation, where the underlying Java VM takes care
of garbage collection. In Java, garbage collection can be defered
indefinitely (actually in CPython also, in the presence of cycles, but
that's another story) so it is *not* guaranteed that the file is
closed by the time you get to the write statement.

Any other question just holler, best regards,
G. Rodrigues



More information about the Tutor mailing list