[Tutor] This is driving my crazy! My file hasn't been corrupted

Steven D'Aprano steve at pearwood.info
Sun Aug 31 21:19:06 CEST 2014


On Sun, Aug 31, 2014 at 09:31:25AM -0700, Richard Dillon wrote:

> My text file has five numbers, 1-5
> I don't what the problem is.

You'll probably find out if you ask Python to show you what is actually 
causing the problem.


> I've written the file using Word (saved as .txt ) as well as TextEdit
> Python 3.4.1 on a Mac
> 
> Here's the code:
> 
> #   Richard Dillon
> 
> #   This program reads data from a .txt file and calculates a total
> #   data in text file: 1,2,3,4 and 5 for a total of 15
> #   error message: Non-numeric data found in the file
> 
> def main():
>     total = 0.0
>     try:
>         infile = open('/Users/richarddillon/Desktop/numbers.txt', 'r')
>         for line in infile:
>             amount = float(line)
>             total += amount
>         infile.close()
>         print(format(total, ',.2f'))
>     except IOError:
>         print('An error occured trying to read the file.')

You don't know that it is a read error. Look at the try block: you do 
SEVEN different things:

- open a file
- read the file
- convert lines of text into floats
- add numbers together
- close the file
- call the format function
- print some string.

All of them could *in principle* raise IOError, although in practice 
only three of them are serious candidates. If you have an IOError, how 
do you know whether it was *opening*, *reading* or *closing* the file 
that failed?

(Yes, closing files can fail.)

Lesson 1: never protect too much by a single try...except block.

Lesson 2: never catch any error that you don't know how to recover from. 
If you *don't* catch the IOError, Python will print the full exception, 
which will show you exactly what failed (say, opening the file), the 
error code, and the error message.

 
>     except ValueError:
>         print('Non-numeric data found in the file.')

Again, there are seven things which could theoretically raise 
ValueError, although this time only one of them is likely to. Never the 
less, the same rule applies: don't protect too much with a try block. In 
this case, this is much more useful:


    infile = open('/Users/richarddillon/Desktop/numbers.txt', 'r')
    for line in infile:
        try:
            amount = float(line)
        except ValueError:
            print(repr(line))
            raise
        total += amount
    infile.close()
    print(format(total, ',.2f'))


The call to repr will convert any weird invisible characters to 
backslash escapes so you can see them. But I suspect what you will see 
is nothing weirder than a blank line:

py> line = '\n'  # blank line
py> float(line)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: could not convert string to float:


>     except:
>         print('An error occured.')

Oh, well that explains everything. "An error occurred." With all that 
diagnostic information, debugging will be so easy!

Not.

Seriously, don't do that. If an error occurs, Python gives you a heap of 
information to make it easy to debug. You collect that information, 
flush it down the toilet, and replace it with an innane and meaningless 
generic message like "An error occurred".


-- 
Steven


More information about the Tutor mailing list