Python 2.7 使用 if elif 遍历文本文件

1 投票
4 回答
6921 浏览
提问于 2025-04-16 10:44

目标是写一个脚本,用来复制一个文本文件,并且排除掉任何以#开头的行。

我想问的是,我似乎遇到了一个索引错误,这个错误的发生和我if和elif条件的顺序有关。非正常工作的代码和正常工作的代码之间唯一的区别(除了非正常工作函数名后面加了"_bad")就是我先测试""这个条件(能正常工作)和先测试"#"这个条件(不能正常工作)。

基础文件是通过这个脚本创建的:

>>> testFileObj = open("test.dat","w")  
>>> testFileObj.write("#line one\nline one\n#line two\nline two\n")  
>>> testFileObj.close()

正常工作的代码:

def copyAndWriteExcludingPoundSigns(origFile, origFileWithOutPounds):    
    origFileObj = open(origFile,"r")  
    modFileObj = open(origFileWithOutPounds,"w")  
    while True:  
        textObj = origFileObj.readline()    
        if textObj == "":    
            break    
        elif textObj[0] == "#":    
            continue    
        else:    
            modFileObj.write(textObj)    
    origFileObj.close()    
    modFileObj.close()    

不正常工作的代码:

def copyAndWriteExcludingPoundSigns_Bad(origFile, origFileWithOutPounds):  
    origFileObj = open(origFile,"r")  
    modFileObj = open(origFileWithOutPounds,"w")  
    while True:  
        textObj = origFileObj.readline()  
        if textObj[0] == "#":  
            continue  
        elif textObj == "":  
            break  
        else:  
            modFileObj.write(textObj)  
    origFileObj.close()  
    modFileObj.close()  

这给我带来了这个错误:

Traceback (most recent call last):
  File "<pyshell#96>", line 1, in <module>
    copyAndWriteExcludingPoundSigns_Bad("test.dat","testOutput.dat")
  File "<pyshell#94>", line 6, in copyAndWriteExcludingPoundSigns_Bad
    if textObj[0] == "#":
IndexError: string index out of range

4 个回答

0

你应该用 line.startswith('#') 来检查字符串 line 是否以 '#' 开头。如果这一行是空的(比如 line = ''),那就没有第一个字符,这样就会出现错误。

另外,文件里可能没有空行,所以像那样直接跳出循环是不太好的做法。在Python中,文件是可以逐行读取的,所以可以直接用 for line in file: 这样的循环。

5

一些小建议(请一定要阅读 PEP8):

  • 用'for'循环代替'while'循环
  • 在Python 2.4之后,不需要再使用readlines
  • 在检查第一字符之前,先检查这一行是否为空

未经测试:

def copy_and_write_excluding_pound_signs(original, filtered):
    original_file = open(original,"r")
    filtered_file = open(filtered,"w")
    for line in original_file:
        if line and line[0] == '#':
            continue
        filtered_file.write(line)
    original_file.close()
    filtered_file.close()

你可能还想过滤掉在'#'之前的一些空格:

import re

def copy_and_write_excluding_pound_signs(original, filtered):
    pound_re = re.compile(r'^\s*#')
    original_file = open(original,"r")
    filtered_file = open(filtered,"w")
    for line in original_file:
        if pound_re.match(line):
            continue
        filtered_file.write(line)
    original_file.close()
    filtered_file.close()
5

如果你执行了

if textObj[0] == "#":
并且 textObj="",那么在零索引位置是没有字符的,因为这个字符串是空的,所以会出现索引错误。

另一种方法是使用

 if textObj.startswith("#"):
,这样在两种情况下都能正常工作。

撰写回答