简体   繁体   English

无法解压缩的值太多(预期为4)

[英]Too many values to unpack (expected 4)

I have this piece of basic code just trying to split a file into 4 lists. 我有一段基本代码,只是试图将一个文件分成4个列表。 The .txt file is formatted as shown underneath the code, with spaces delimiting each number. .txt文件的格式如代码下方所示,并用空格分隔每个数字。 The error appearing is 'ValueError: too many values to unpack (expected 4)'. 出现的错误是“ ValueError:太多值无法解包(预期为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)'. 但是,我将代码更改为如下所示,以测试它期望有多少个变量,并且错误更改为“没有足够的值要解压(预期为5,得到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 ). 正如评论者所建议的那样,请尝试打印该行以查看实际上引起问题的行(但请确保将打印内容插入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: 如果是这样,最简单的解决方案可能是在if语句上附加另一个条件:

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. 第二个if语句更健壮,因为它仅在要使用四个列表条目的情况下才会尝试提取四个变量。 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. 您可以根据需要对它进行更多调整,例如,如果您还希望读取更长的行,可以将其更改为“ len(line)> = 4”。

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. 老实说,我想不出try / except变体的特殊优势,但是由于我只是写了出来,所以我不妨保留它。实际上,它可能太强大了,因为它也会跳过导致比没有过于几个条目一起工作原因ValueErrors线。

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. 您要告诉python将四个条目的列表分成五个变量,即v,a,t,y和test。 That's what the error is referring to when it says, 'expected 5, got 4'. 这就是错误所指的,即“预期5,得到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: 第二个错误是正确的,因为您要按照以下行解压缩5个值:

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. 由于分割时的每一行将返回4个元素,因此不存在第5个值,因此会出现错误。 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 ). 对于您的原始问题,请尝试使用line.split()因为这会自动在空格上拆分-即,空格可能是制表符或空白的Unicode字符之一(请参阅: 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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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