解包的值太多(预计4)

时间:2017-12-05 23:01:58

标签: python list line

我有这段基本代码只是试图将文件拆分为4个列表。 .txt文件的格式如代码下方所示,每个数字都用空格分隔。出现的错误是'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
...

但是,我将代码更改为如下所示,以测试它所期望的变量数,并将错误更改为“没有足够的值来解包(预期5,得到4)”。这没有意义,因为现在代码正在解包我想要的四个变量!任何解决方案/指针都会非常感激。

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

2 个答案:

答案 0 :(得分:1)

正如评论者建议的那样,尝试打印该行以查看实际导致问题的行(但务必在line.split之前插入打印件)。

最可能的问题是末尾有一个空白行,它被读作换行符。如果是这样,最简单的解决方案可能是针对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(' ')

或者尝试/除了:

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

第二个if语句更健壮,因为如果有四个列表项可以使用,它只会尝试提取四个变量。任何其他情况(从中提取更多或更少的条目)将被忽略。您可以根据自己的需要量身定制,例如:如果你想允许读取更长的行,可以将它改为'len(line)> = 4'。

说实话,我不能想到try / except变体的特殊优势,但是因为我刚刚把它写出来我不妨留下它。事实上,它可能有点过于强大了,因为它还会跳过因其他而导致ValueErrors的行,而不是使用的条目太少。

你所描述的第二次尝试失败是完全合理的。 你告诉python将四个条目的列表分成五个变量,v,a,t,y和test。这就是错误指的是什么,它说'预期5,得到4'。您的错误行为可能已更改,因为代码现在很快就会失败。在它为除最后一行之外的所有行工作之前,只有一个列表条目可供使用。如果您更改为五个变量,则会导致第一行出错,其中有四个条目,但现在您要求五个。

答案 1 :(得分:0)

第二个错误是正确的,因为您按照此行解压缩了5个值:

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

由于拆分时每行返回4个元素,因此不存在第5个值,因此出错。请注意,从长远来看,以这种方式使用拆包可能会有问题,特别是对于许多元素。可能值得检查一下对分割线长度的明确检查。

对于您的原始问题,请尝试使用line.split(),因为这会自动拆分空格 - 即空格可能是标签或空白unicode字符之一(请参阅:{{3 }})。

或者,可以在线上使用正则表达式,这可以简化解析文本:

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