在python文件处理中混合使用readline()和行迭代器安全吗?

在python文件处理中混合使用readline()和行迭代器安全吗?,python,file-io,Python,File Io,使用readline()读取某些行,并对文件中的行使用,是否安全?是否保证使用相同的文件位置 通常,我想忽略第一行(标题),所以我这样做: FI = open("myfile.txt") FI.readline() # disregard the first line for line in FI: my_process(line) FI.close() 这是否安全,即,是否保证在迭代行时使用相同的文件位置变量?从长远来看,这很有效。它忽略了您正在处理文件的事实

使用
readline()
读取某些行,并对文件中的行使用
,是否安全?是否保证使用相同的文件位置

通常,我想忽略第一行(标题),所以我这样做:

FI = open("myfile.txt")
FI.readline()             # disregard the first line
for line in FI:
    my_process(line)
FI.close()

这是否安全,即,是否保证在迭代行时使用相同的文件位置变量?

从长远来看,这很有效。它忽略了您正在处理文件的事实,并且可以处理任何序列。另外,使用显式迭代器对象(
rdr
)可以跳过for循环主体内的行,而不会弄乱任何东西

with open("myfile.txt","r") as source:
    rdr= iter(source)
    heading= next(rdr)
    for line in rdr:
        process( line )
没有

由于使用了预读 缓冲区,将next()与其他 文件方法(如readline())可以 工作不正常

您可以使用
next()
跳过这里的第一行。您还应该测试
StopIteration
,如果文件为空,将引发该测试

with open('myfile.txt') as f:
    try:
        header = next(f)
    except StopIteration as e:
        print "File is empty"
    for line in f:
        # do stuff with line

如果这些机制在控制之下是安全的

=============================

在执行readline()指令后进行迭代没有问题

但是有一种方法可以在迭代后执行readline()

我用此文本创建了一个“rara.txt”文件(由于Windows下的“\r\n”行结尾,每行的长度为5)

我执行了

FI  = open("rara.txt",'rb')
lineR = FI.readline()
print repr(lineR)+'   len=='+str(len(lineR))+\
      '  FI.tell() after FI.readline() : ',FI.tell(),'\n'

cnt = 0
for line in FI:
    cnt += 1
    print 'cnt=='+str(cnt)+'   '+repr(line)+'   len=='+str(len(line))+\
          "  FI.tell() after 'line in FI' : ",FI.tell()
    if cnt==4:
        break
print "\nFI.tell() after iteration 'for line in FI' : ",FI.tell(),'\n'


lineR = FI.readline()
print repr(lineR)+'   len=='+str(len(lineR))+\
      '  FI.tell() after FI.readline() : ',FI.tell()
lineR = FI.readline()
print repr(lineR)+'   len=='+str(len(lineR))+\
      '  FI.tell() after FI.readline() : ',FI.tell(),'\n'

for line in FI:
    print 'cnt=='+str(cnt)+'   '+repr(line)+'   len=='+str(len(line))+\
          "  FI.tell() after 'line in FI' : ",FI.tell()
print "\nFI.tell() after iteration 'for line in FI' : ",FI.tell(),'\n'
结果是

'1AA\r\n'   len==5  FI.tell() after FI.readline() :  5 

cnt==1   '2BB\r\n'   len==5  FI.tell() after 'line in FI' :  75
cnt==2   '3CC\r\n'   len==5  FI.tell() after 'line in FI' :  75
cnt==3   '4DD\r\n'   len==5  FI.tell() after 'line in FI' :  75
cnt==4   '5EE\r\n'   len==5  FI.tell() after 'line in FI' :  75

FI.tell() after iteration 'for line in FI' :  75 


Traceback (most recent call last):
  File "E:\Python\NNN codes\esssssai.py", line 16, in <module>
    lineR = FI.readline()
ValueError: Mixing iteration and read methods would lose data
结果

'1AA\r\n'   len==5  FI.tell() after FI.readline() :  5 

cnt==1   '2BB\r\n'   len==5  FI.tell() after 'line in FI' :  75
cnt==2   '3CC\r\n'   len==5  FI.tell() after 'line in FI' :  75
cnt==3   '4DD\r\n'   len==5  FI.tell() after 'line in FI' :  75
cnt==4   '5EE\r\n'   len==5  FI.tell() after 'line in FI' :  75

FI.tell() after iteration 'for line in FI' :  75 

''   len==0  FI.tell() after FI.readline() :  75
''   len==0  FI.tell() after FI.readline() :  75 


FI.tell() after iteration 'for line in FI' :  75 
'1AA\r\n'   len==5  FI.tell() after FI.readline() :  5 

cnt==1   '2BB\r\n'   len==5  FI.tell() after 'line in FI' :  75
cnt==2   '3CC\r\n'   len==5  FI.tell() after 'line in FI' :  75
cnt==3   '4DD\r\n'   len==5  FI.tell() after 'line in FI' :  75
cnt==4   '5EE\r\n'   len==5  FI.tell() after 'line in FI' :  75

FI.tell() after iteration 'for line in FI' :  75
    pos   after iteration 'for line in FI' :  25 

'6FF\r\n'   len==5  FI.tell() after FI.readline() :  30
'7GG\r\n'   len==5  FI.tell() after FI.readline() :  35 

cnt==1   '8HH\r\n'   len==5  FI.tell() after 'line in FI' :  75
cnt==2   '9II\r\n'   len==5  FI.tell() after 'line in FI' :  75
cnt==3   '10j\r\n'   len==5  FI.tell() after 'line in FI' :  75
cnt==4   '11k\r\n'   len==5  FI.tell() after 'line in FI' :  75
cnt==5   '12l\r\n'   len==5  FI.tell() after 'line in FI' :  75
cnt==6   '13m\r\n'   len==5  FI.tell() after 'line in FI' :  75
cnt==7   '14n\r\n'   len==5  FI.tell() after 'line in FI' :  75
cnt==8   '15o\r\n'   len==5  FI.tell() after 'line in FI' :  75

FI.tell() after iteration 'for line in FI' :  75 
无论如何,我们注意到,即使算法在迭代期间仅读取4行(由于countcnt),光标从迭代开始就已经位于文件的末尾:在迭代开始时,位于当前位置之前的所有文件都会被一次读取

因此,在中断之前,pos=FI.tell()不会给出读取4行之后的位置,而是给出文件结尾的位置


如果我们想在迭代后再次读取行(),我们必须做一些特别的事情,从迭代过程中4行读取结束的确切点开始:

FI  = open("rara.txt",'rb')
lineR = FI.readline()
print repr(lineR)+'   len=='+str(len(lineR))+\
      '  FI.tell() after FI.readline() : ',FI.tell(),'\n'

cnt = 0
pos = FI.tell()
for line in FI:
    cnt += 1
    pos += len(line)
    print 'cnt=='+str(cnt)+'   '+repr(line)+'   len=='+str(len(line))+\
          "  FI.tell() after 'line in FI' : ",FI.tell()
    if cnt==4:
        break
print "\nFI.tell() after iteration 'for line in FI' : ",FI.tell()
print "    pos   after iteration 'for line in FI' : ",pos,'\n'

FI.seek(pos)

lineR = FI.readline()
print repr(lineR)+'   len=='+str(len(lineR))+\
      '  FI.tell() after FI.readline() : ',FI.tell()
lineR = FI.readline()
print repr(lineR)+'   len=='+str(len(lineR))+\
      '  FI.tell() after FI.readline() : ',FI.tell(),'\n'

cnt = 0
for line in FI:
    cnt += 1
    print 'cnt=='+str(cnt)+'   '+repr(line)+'   len=='+str(len(line))+\
          "  FI.tell() after 'line in FI' : ",FI.tell()
print "\nFI.tell() after iteration 'for line in FI' : ",FI.tell(),'\n'
结果

'1AA\r\n'   len==5  FI.tell() after FI.readline() :  5 

cnt==1   '2BB\r\n'   len==5  FI.tell() after 'line in FI' :  75
cnt==2   '3CC\r\n'   len==5  FI.tell() after 'line in FI' :  75
cnt==3   '4DD\r\n'   len==5  FI.tell() after 'line in FI' :  75
cnt==4   '5EE\r\n'   len==5  FI.tell() after 'line in FI' :  75

FI.tell() after iteration 'for line in FI' :  75 

''   len==0  FI.tell() after FI.readline() :  75
''   len==0  FI.tell() after FI.readline() :  75 


FI.tell() after iteration 'for line in FI' :  75 
'1AA\r\n'   len==5  FI.tell() after FI.readline() :  5 

cnt==1   '2BB\r\n'   len==5  FI.tell() after 'line in FI' :  75
cnt==2   '3CC\r\n'   len==5  FI.tell() after 'line in FI' :  75
cnt==3   '4DD\r\n'   len==5  FI.tell() after 'line in FI' :  75
cnt==4   '5EE\r\n'   len==5  FI.tell() after 'line in FI' :  75

FI.tell() after iteration 'for line in FI' :  75
    pos   after iteration 'for line in FI' :  25 

'6FF\r\n'   len==5  FI.tell() after FI.readline() :  30
'7GG\r\n'   len==5  FI.tell() after FI.readline() :  35 

cnt==1   '8HH\r\n'   len==5  FI.tell() after 'line in FI' :  75
cnt==2   '9II\r\n'   len==5  FI.tell() after 'line in FI' :  75
cnt==3   '10j\r\n'   len==5  FI.tell() after 'line in FI' :  75
cnt==4   '11k\r\n'   len==5  FI.tell() after 'line in FI' :  75
cnt==5   '12l\r\n'   len==5  FI.tell() after 'line in FI' :  75
cnt==6   '13m\r\n'   len==5  FI.tell() after 'line in FI' :  75
cnt==7   '14n\r\n'   len==5  FI.tell() after 'line in FI' :  75
cnt==8   '15o\r\n'   len==5  FI.tell() after 'line in FI' :  75

FI.tell() after iteration 'for line in FI' :  75 

所有这些操作都是可能的,因为文件是在二进制模式下打开的,因为我在Windows上使用“\r\n”作为行尾来写入文件,即使它被命令写入(在“w”模式下)类似“abcdef\n”的内容

另一方面,Python(在“r”模式下)转换“\r\n”中的所有“\r\n”

这真是一团糟,为了控制这一切,如果我们想进行精确的操作,必须用“rb”打开文件



你知道吗?我喜欢这些文件位置的游戏

最好使用
next
函数。因为
.next
已经在py3k中消失了。相应地编辑(迟做总比不做好;-)@Simon Whitaker@highBandWidth Simon,你敷衍的回答传播了一个错误的概念。首先,您的引用是不完整的:在您的引用之后,文档的文本继续:“(..)工作不正常。但是,使用seek()将文件重新定位到绝对位置将刷新预读缓冲区。”也就是说,通过一些精确的控制和理解,可以混合不同的文件读取方法。其次,您显然没有进行一些测试来加深对这些过程的理解。@eyquem-我回答了最初的问题:“所以我这样做:-安全吗?”。对于该代码段,答案是否定的。您可以使用seek()重新定位文件光标,这是正确的,但您反过来忽略了并非所有文件对象都是可查找的。(比如说,你不能在STDIN上寻求回击。)我很高兴同意在这一点上有不同意见这个石头!>>“挂起显式迭代器对象(rdr)可以让您跳过for循环体中的行,而不会弄乱任何东西。”