简体   繁体   中英

Tuples | Converting Strings to Floats

I'm following along with a Great Course tutorial for learning Python, and this code doesn't seem to work.

#Open File
filename = input("Enter the name of the data file: ")
infile = open(filename, 'r')

#Read in file
datalist = []

for line in infile:
    #Get data from line
    date, l, h, rf = (line.split(','))
    rainfall = float(rf)
    max_temp = float(h)
    min_temp = float(l)
    m, d, y = (date.split('/'))
    month = int(m)
    day= int(d)
    year=int(y)
    #Put data into list
    datalist.append([day,month,year,min_temp,max_temp,rainfall])

I'm trying to import a csv file, then create a tuple. The problem occurs when I'm converting the values in the tuple to floats. It works fine until it runs through the file. Then it presents me with this error:

Traceback (most recent call last): File "C:/Users/Devlin/PycharmProjects/untitled3/James' Programs/Weather.py", line 16, in rainfall = float(rf) ValueError: could not convert string to float:`

Any ideas on what am doing wrong?

It's hard to tell what exactly are you doing wrong without seeing the input file itself, but what seems to be wrong here (besides the fact that your values in a file seem to be comma-separated and that you might have been better off using Python stdlib's csv module) is that you're encountering a string somewhere when iterating over the lines, and are trying to convert that to float which is a no go:

>>> float('spam')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: could not convert string to float: 'spam'

One of the solutions would be to simply skip the strings you're encountering, and you can choose between two approaches there ( LBYL (Look Before You Leap) vs EAFP (Easier to Ask for Forgiveness than Permission) ), and, in a nutshell, I suggest you go with the latter since it's generally preferred due to the gap that exists between checking and using, which means that things can change out from under you, and oftentimes you'll have to handle the error in any case, even if you check first. Apart from that, instead of manually closing file-like objects later on (which you seem to have forgotten to do), I suggest using with statement as a context manager which automatically manages that for you. So, taking all that into account, something along the following lines should do the trick (disclaimer: not thoroughly tested):

import csv

data = []

filename = input('Enter the name of the data file: ')

with open(filename) as f:
    reader = csv.reader(f, delimiter=',', skipinitialspace=True)
    for line in reader:
        try:
            date, (l, h, rf) = line[0], map(float, line[1:])
            m, d, y = map(int, date.split('/'))
        except ValueError as e:
            print('Skipping line: %s [because of: %s]' % (line, e))
            continue
        data.append([d, m, y, l, h, rf])

Hopefully this is enough to get you back on track ;-)

Review your csv file.

It is hard to say without seeing what's in the file, but the most likely explanation (according to the error message) is that you have a line for which the forth value is empty, eg:

2018-01-30,5,12,

So the rf variable would be empty when parsing that line, and the you would get that ValueError when trying to cast the value as a float.

Also, some advice on how to do it better:

  • You may want to split your line first, then count how many data fields it has, and then discarding it before assigning the whole line to date, l, h, rf . Something like this:

`

for line in infile:
    # Get data from line. Use strip() to avoid whitespace
    items = line.strip().split(',')
    if len(items) != 4:
        # skip the iteration - do nothing with that malformed line
        continue
    date, l, h, rf = items

`

  • You may want to have a look at the csv module for reading/writing csv files easily.

The error means you that the string you are trying to cast a float is actually not a number. In your case, it looks like it's an empty string. It's probably because the last line of your file is empty, so you can check it at the beginning of your loop and break or continue if it is. An other strategy would be to catch the error, but it would then ignore a malformed line when you could want to be alerted of it, so it's up to you to pick the one that suites you.

Using square brackets also puts your values in a list, not in a tuple. You need parenthesis for that.

And you should also close your files when you are done.

Python also has a CSV module you may find useful.

#Open File
filename = input("Enter the name of the data file: ")
infile = open(filename, 'r')

#Read in file
datalist = []

for line in infile:
    if line.strip() == '': # If the line only contains spaces
        continue           # Then, just skip it

    # Some stuff ...

    # Put everything in a tuple that we add to our list
    datalist.append((day,month,year,min_temp,max_temp,rainfall))

infile.close() # Close the file

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM