我正在尝试循环文本文件并应用一些逻辑,但我无法遍历文本文件。所以目前我有一个文本文件,结构如下:
--- section1 ---
"a","b","c"
"d","e","f"
--- section2 ---
"1","2","3"
"4","5","6"
--- section3 ---
"12","12","12"
"11","11","11"
我试图过滤出包含'---'的第一行,并将下面的行转换为json,直到下一行'---'行出现在文本文档中。
但是我收到此错误“ fields1 = next(file).split(',')StopIteration
with open(fileName,'r') as file:
for line in file:
if line.startswith('-') and 'section1' in line:
while '---' not in next(file):
fields1 = next(file).split(',')
for x in range(0,len(fields1)):
testarr.append({
config.get('test','test'): fields1[x]
})
with open(test_dir,'w') as test_file:
json.dump(testarr, test_file)
知道为什么我的代码不起作用或我如何解决错误?
答案 0 :(得分:2)
看起来你大量过分复杂。我想象的内部next
循环中的while
正在绊倒外部for
循环,但这无论如何都是不必要的。你已经在线上循环了;选择你想要的,然后在你完成后退出。
with open(fileName,'r') as inputfile:
for line in inputfile:
if line.startswith('-') and 'section1' in line:
continue
elif line.startswith('-'):
break
else:
testarr.append({config.get('test', 'test'): x
for x in line.split(',')})
with open(test_dir,'w') as test_file:
json.dump(testarr, test_file)
我希望我得到append
权利,因为我还想向您展示如何更优雅地映射分割字段,但我不确定我是否完全理解您的原始代码所做的事情。 (我猜你实际上想要在分割之前修剪掉\n
行。然后,我想你想要修剪每个值周围的引号。x.strip('"') for x in line.rstrip('\n').split(',')
)
我还将file
重命名为inputfile
,以避免与保留关键字file
发生冲突。
如果要编写更多文件,基本上,在循环中添加更多状态,并将写代码段移回循环内部。我不是特别想解释它是如何等同于状态机的,但它应该不难理解:有两个状态,你正在跳过或收集;为了扩展这一点,在翻转时为边界添加一个状态,在此处写出收集的数据并将收集的行重新初始化为无。
答案 1 :(得分:2)
您的错误的原因是您滥用文件对象生成器时通过调用next
两次,就像您想象的那样频繁。每次调用next
都会获得一行并将其返回。因此,while '---' not in next(file): fields1 = next(file).split(',')
获取一行,检查---
,然后获取另一行并尝试解析它。这意味着您可以跳过包含---
的行,使其出现在第二个next
中。在这种情况下,您将在找到要查找的行之前到达文件的末尾。 StopIteration
是迭代器通常表明其输入已用尽的方式。
您可能希望在代码中解决其他一些问题:
next
循环内时,在文件生成器上使用for
可能会导致未定义的行为。这次你可能会侥幸成功,但这并不是一般的好习惯。顺便说一下,你逃避它的主要原因可能是,一旦for
被触发,你永远不会真正将控制权返回到while
循环,而且这方面的文件并不是特别宽容with
位于while
循环内。这意味着您使用'w'
权限打开的文件将在while
的每次迭代(即文件中的每一行)中被截断。随着数组的增长,输出实际上看起来很好,但你可能想要将它移出内循环。最简单的解决方案是在两个循环中重写代码:一个用于查找您关注的部分的开头,另一个用于处理它直到找到结束。
这样的事情:
test_arr = []
with open(fileName, 'r') as file:
for line in file:
if line.startswith('---') and 'section1' in line:
break
for line in file:
if '---' in line:
break
fields1 = line.split(',')
for item in fields1:
testarr.append({config.get('test','test'): item})
with open(test_dir,'w') as test_file:
json.dump(testarr, test_file)
编辑:
考虑到@ tripleee的建议,我已经删除了起始行的正则表达式检查。虽然正则表达式为查找特定模式提供了极高的精度和灵活性,但对于这个例子来说这实在是太过分了。我想指出,如果你正在寻找除section1之外的部分,或者如果section1出现在带有破折号的其他行之后,那么你绝对需要这种双循环方法。其他答案中的单循环解决方案不适用于非平凡的情况。
答案 2 :(得分:0)
next()
会引发StopIteration
异常。换句话说,你的代码到达文件的末尾,然后再次调用next()
,并且没有更多内容可以返回,因此它会引发异常。
至于如何解决问题,我想这可能是你想要的:
with open(fileName, 'r') as file:
for line in file:
if line.startswith('---'):
if 'section1' in line:
continue
else:
break
fields1 = line.split(',')
for x in range(len(fields1)):
testarr.append({
config.get('test', 'test'): fields1[x]
})
with open(test_dir, 'w') as test_file:
json.dump(testarr, test_file)