简体   繁体   中英

Too many values to unpack (expected 4)

I have this piece of basic code just trying to split a file into 4 lists. The .txt file is formatted as shown underneath the code, with spaces delimiting each number. The error appearing is 'ValueError: too many values to unpack (expected 4)'.

file = open("myfreefall.txt","r")
for line in file:
     if not line.startswith('#'):
         v,a,t,y= line.split(' ')


#v  a  t  y
-0.10 -9.81 0.01 5500.00
-0.20 -9.81 0.02 5500.00
-0.29 -9.81 0.03 5500.00
-0.39 -9.81 0.04 5499.99
-0.49 -9.81 0.05 5499.99
-0.59 -9.81 0.06 5499.99
-0.69 -9.81 0.07 5499.98
-0.78 -9.81 0.08 5499.97
...

However I changed the code to be as shown below to test how many variables it was expecting, and the error changed to 'not enough values to unpack (expected 5, got 4)'. This doesn't make sense as now the code is unpacking the four variables I wanted! Any solutions/pointers would be much appreciated.

file = open("myfreefall.txt","r")
for line in file:
     if not line.startswith('#'):
         v,a,t,y,test= line.split(' ')

As commenters have suggested, try printing the line to see the line that's actually causing a problem (but be sure to insert the print before the line.split ).

The most likely problem is a blank line at the end, which is read as a newline character. If so the easiest solution is probably to tack on another condition to the if statement:

file = open("myfreefall.txt","r")
for line in file:
     if not line.startswith('#') and line != '\n':
     # or, more robust:
     if not line.startswith('#') and len(line) == 4:
         v,a,t,y= line.split(' ')

Or with a try/except:

file = open("myfreefall.txt","r")
for line in file:
    try:
       v,a,t,y= line.split(' ')
    except ValueError:
       continue
       # Skip over this line if the extraction fails

The second if-statement is more robust because it will only try to extract your four variables if there are exactly four list entries to work with. Any other case (more or fewer entries to extract from) will be ignored. You can tailor it a bit more to your needs, eg by changing it to 'len(line) >= 4' if you wanted to allow longer lines to be read as well.

To be honest, I can't think of a particular advantage for the try/except variant, but since I just wrote it out I might as well leave it in. It might be a bit too robust, in fact, because it would also skip lines that cause ValueErrors for reasons other than there being too few entries to work with.

Your second attempt failing as you describe makes perfect sense. You're telling python to split a list of four entries into five variables, v, a, t, y and test. That's what the error is referring to when it says, 'expected 5, got 4'. The behaviour of your error probably changed because the code fails a lot sooner now. Before it was working for all lines except the last one, where there's only one list entry to use. With your change to five variables it's causing an error with the very first line, where there are four entries but now you're asking for five.

The second error is correct since you're unpacking 5 values as per this line:

v,a,t,y,test = line.split(' ')
#       ^^^^

Since each line when split will return 4 elements, a 5th value is non-existent, hence the error. Note that using unpacking this way can be problematic in the long run, particularly with many elements. It may be worth examining doing an explicit check on the length of the split line.

For your original problem, try using line.split() since this automatically splits on whitespace - ie it's possible that the space may be a tab, or one of the blank unicode characters (see: http://jkorpela.fi/chars/spaces.html ).

Or, one could use a regex on the line which could simplify parsing the text:

import re

regex = re.compile('([-+]?[0-9]*\.[0-9]+|[0-9]+)')  # regex for floating-point numbers
matches = regex.findall(line)  # `matches` will return a list

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