ast.literal_eval不能作为列表推导式的一部分工作(当读取文件时)



我试图解析一个文件,其中有对行,每一个代表整数或其他列表的列表。文件中的示例数据:

[[[6,10],[4,3,[4]]]]
[[4,3,[[4,9,9,7]]]]
[[6,[[3,10],[],[],2,10],[[6,8,4,2]]],[]]
[[6,[],[2,[6,2],5]]]

我试图用以下语句将文件读取为数据结构元组(嵌套列表)的列表:

with open("filename","r") as fp:
pairs = [tuple(ast.literal_eval(l.strip()) for l in lines.split("n")) for lines in fp.read().split("nn")]

这在下面的stacktrace中失败了,导致我相信数据在某处损坏了(不匹配的括号或类似的东西):

Traceback (most recent call last):
File "program.py", line 5, in <module>
pairs = [tuple(ast.literal_eval(l.strip()) for l in lines.split("n")) for lines in fp.read().split("nn")]
File "program.py", line 5, in <listcomp> 
pairs = [tuple(ast.literal_eval(l.strip()) for l in lines.split("n")) for lines in fp.read().split("nn")]
File "program.py", line 5, in <genexpr>  
pairs = [tuple(ast.literal_eval(l.strip()) for l in lines.split("n")) for lines in fp.read().split("nn")]
File "C:Python39libast.py", line 62, in literal_eval
node_or_string = parse(node_or_string, mode='eval')
File "C:Python39libast.py", line 50, in parse
return compile(source, filename, mode, flags,
File "<unknown>", line 0
SyntaxError: unexpected EOF while parsing

所以我把程序缩减为手动循环,问题就不再重现了。所以下面的代码,首先读入字符串元组的列表,然后用ast.literal_eval计算字符串,工作得很好。上面提到的"一次完成所有事情";仍然失败,并出现相同的错误

# This works:
with open("filename","r") as fp:
stringpairs = [tuple(l.strip() for l in lines.split("n")) for lines in fp.read().split("nn")]
pairs = [tuple(ast.literal_eval(pair[i]) for i in range(2)) for pair in stringpairs]
# This still doesn't work:
with open("filename","r") as fp:
pairs = [tuple(ast.literal_eval(l.strip()) for l in lines.split("n")) for lines in fp.read().split("nn")]

问题是fp.read().split("nn")在最后一对行的末尾留下了最后一个换行符。

当你做lines.split('n')时,你在最后一组中得到3行,而不仅仅是2行;该组最后一行为空,ast.literal_eval('')报错。

在调用lines.split('n')之前去掉换行符

pairs = [tuple(ast.literal_eval(l.strip()) 
for l in lines.strip().split("n")) 
for lines in fp.read().split("nn")]

好的,我找到原因了。在文件末尾没有空行(最后一行之后有一个换行),所以nn上的外部分割将其分割成正确的段,但是第一个段(除了最后一个)看起来像line1nline2,最后一个段看起来像line42nline43n。现在,n的内部拆分将其分成三部分,line42,line42和空字符串,并且由于ast.literal_eval在拆分的所有项目上都被调用,因此它也在失败的空字符串上被调用。

第二个解决方案避免了它,因为它不遍历元组的所有元素,而只显式地遍历前两个元素。

在这种情况下,只要去掉开头和结尾,问题就解决了!

import ast
with open("file.txt", "w") as file:
file.write("[[[6,10],[4,3,[4]]]]n")
file.write("[[4,3,[[4,9,9,7]]]]n")
file.write("n")
file.write("[[6,[[3,10],[],[],2,10],[[6,8,4,2]]],[]]n")
file.write("[[6,[],[2,[6,2],5]]]n") # evil newline
pairs = []
with open("file.txt","r") as file:
pairs = [tuple(ast.literal_eval(line.strip()) for line in multiline.split("n")) for multiline in file.read().strip().split("nn")]
for pair in pairs:
print(pair)

输出:

([[[6, 10], [4, 3, [4]]]], [[4, 3, [[4, 9, 9, 7]]]])
([[6, [[3, 10], [], [], 2, 10], [[6, 8, 4, 2]]], []], [[6, [], [2, [6, 2], 5]]])

相关内容

  • 没有找到相关文章

最新更新