首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Python I/O索引超出范围,不是off-by-one错误(我认为)

Python I/O索引超出范围,不是off-by-one错误(我认为)
EN

Stack Overflow用户
提问于 2012-07-21 05:13:18
回答 3查看 462关注 0票数 0

我有这个简单的代码,它只是为了帮助我理解Python I/O是如何工作的:

代码语言:javascript
复制
inFile = open("inFile.txt",'r')
outFile = open("outFile.txt",'w')
lines = inFile.readlines()

first = True
for line in lines:
    if first == True:
        outFile.write(line)  #always print the header
        first = False
        continue
    nums = line.split()
    outFile.write(nums[3] + "\n") #print the 4th column of each row
outFile.close()

我的输入文件是这样的:

代码语言:javascript
复制
#header
34.2 3.42 64.56 54.43 3.45
4.53 65.6 5.743 34.52 56.4
4.53 90.8 53.45 134.5 4.58
5.76 53.9 89.43 54.33 3.45

输出按照应该的方式打印到文件中,但我也得到了错误:

代码语言:javascript
复制
    outFile.write(nums[3] + "\n")
IndexError: list index out of range 

我假设这是因为它继续读取下一行,尽管不再有任何数据?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2012-07-21 05:30:16

其他人已经回答了你的问题。这里有一个更好的方法来“总是打印出文件头”,避免在每次迭代中测试first

代码语言:javascript
复制
with open('inFile.txt', 'r') as inFile, open('outFile.txt', 'w') as outFile:
    outFile.write(inFile.readline()) #always print the header
    for line in inFile:
        nums = line.split()
        if len(nums) >= 4: #Checks to make sure a fourth column exists.
            outFile.write(nums[3] + "\n") #print the 4th column of each row

这里发生了几件事:

代码语言:javascript
复制
with open('inFile.txt', 'r') as inFile, open('outFile.txt', 'w') as outFile:

with表达式是一种打开文件的便捷方法,因为即使发生异常并且with块提前退出,它也会自动关闭文件。

注意:在Python2.6中,您将需要使用两个with语句,因为直到2.7才添加了对多上下文的支持。例如:

代码语言:javascript
复制
with open(somefile, 'r') as f:
    with open(someotherfile, 'w') as g:
        #code here.

代码语言:javascript
复制
outFile.write(inFile.readline()) #always print the header

file对象是一个被使用的迭代器。当调用readline()时,缓冲区位置向前移动并返回第一行。

代码语言:javascript
复制
for line in inFile:

如前所述,file对象是一个迭代器,因此可以在for循环中直接使用它。

票数 2
EN

Stack Overflow用户

发布于 2012-07-21 05:14:56

该错误显示您的源代码中包含以下行:

代码语言:javascript
复制
outFile.write(nums[6] + "\n")  

请注意,这里的6与您在问题中显示的3不同。您可能有两个不同版本的文件。

它失败了,因为nums是拆分一行的结果,在本例中它只包含5个元素:

代码语言:javascript
复制
for line in lines:
    # ...
    # line is for example "34.2 3.42 64.56 54.43 3.45"
    nums = line.split() 
    print len(nums)

索引不能超过列表的末尾。

您的代码中也可能存在错误。您编写头部,然后将其拆分并从中写入一个元素。您可能需要一个if/else。

代码语言:javascript
复制
for line in lines:
    if first == 1: 
        # do something with the header
    else:
        # do something with the other lines

或者,您可以在进入循环之前单独处理头文件。

票数 2
EN

Stack Overflow用户

发布于 2012-07-21 05:15:19

问题是,您正在处理“标题行”,就像处理其他数据一样。也就是说,即使你识别了标题行,你也不会跳过它的处理。也就是说,你不能避免在循环中进一步split()它,这会导致运行时错误。

要解决问题,只需插入continue即可,如下所示:

代码语言:javascript
复制
first = True
for line in lines:
    if first == True:
       outFile.write(line)  #always print the header
       first = False
       continue   ## skip the rest of the loop and start from the top 
    nums = line.split()
    ...

这将绕过循环的其余部分,一切都将按其应有的方式工作。

输出文件outFile.txt将包含:

代码语言:javascript
复制
#header
54.43
34.52
134.5
54.33

第二个问题是在输入文件的末尾有空行(参见下面注释中的讨论)

注意:您可以重构代码,但是如果您对此不感兴趣,上面的简单修复方法可以让您保留所有当前代码,并且只需要添加一行代码。正如在其他帖子中提到的,值得研究一下使用with来管理您打开的文件,因为当您完成管理或遇到异常时,它也会为您关闭这些文件。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/11587012

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档