Python3中readlines或enumerate读取文件是否会导致文件流为空?

python3 环境 代码如下:

file_path = os.getcwd() + "/test.txt"
project_file = open(file_path,"r")
#list_file = project_file.readlines()
for index, line in enumerate(project_file):
    print("index=%d,linex=%s"%(index,line))

test.txt 里面有一些任意文本内容,在注释掉第三行的情况下,下面的 print 能正常打印文本内容。 去除第三行的注释后,下面的 print 无打印,也就是 project_file 为空了? 同样的把 for 循环放到 readlines 上面,第一个 print 能正常打印文本内容,但是也会导致 list_file 为空,print 打出的长度为 0,代码如下:

file_path = os.getcwd() + "/test.txt"
project_file = open(file_path,"r")
for index, line in enumerate(project_file):
    print("index=%d,linex=%s"%(index,line))
list_file = project_file.readlines()
print(len(list_file))

我的问题是:enumerate 或者 readlines 操作过一次文件流后,是否会导致文件流为空?或者是我的使用有问题,我是 python 新手,求大佬解惑


Python3中readlines或enumerate读取文件是否会导致文件流为空?

3 回复

事实上是不会的
In [1]: with open(file=‘README.md’, mode=‘r’, encoding=‘utf8’) as f:
…: res = f.readlines()
…:

In [2]: res
Out[2]: [‘这次会有比较多的代码,但核心代码都是你已经亲自写过的~\n’, ‘请注意阅读顺序,ext 会作为课外阅读内容~’]

In [3]: for index, value in enumerate(res):
…: print(index, value)
…:
0 这次会有比较多的代码,但核心代码都是你已经亲自写过的~

1 请注意阅读顺序,ext 会作为课外阅读内容~


这个问题其实挺常见的,很多人都会遇到。简单来说,是的,如果你用 readlines()for line in enumerate(file) 完整地读取了一个文件对象,那么这个文件对象的“流”就到达了末尾(EOF)。 之后你再对这个文件对象进行读取操作,比如再次调用 read()readline() 或进行迭代,就不会得到任何数据了。

这是因为文件对象内部有一个“指针”,用来记录当前读取的位置。readlines()enumerate(file)(本质上就是迭代文件对象)都会从头读到尾,指针就移到了文件末尾。

看个例子就明白了:

# 假设我们有一个文件 test.txt,内容为:
# Line 1
# Line 2
# Line 3

with open('test.txt', 'r') as f:
    # 第一次读取:使用 readlines(),会消耗掉整个文件流
    lines = f.readlines()
    print("第一次读取 (readlines):", lines)  # 输出:['Line 1\n', 'Line 2\n', 'Line 3\n']

    # 此时文件流指针已在末尾
    # 第二次尝试读取:什么也得不到
    second_read = f.readlines()
    print("第二次读取 (readlines):", second_read)  # 输出:[]

    # 同样,尝试 readline() 也返回空字符串
    line = f.readline()
    print("尝试 readline():", repr(line))  # 输出:''

    # 迭代也不会产生任何结果
    for i, line in enumerate(f):
        print("这行不会被执行")

解决办法很简单:

  1. 重新打开文件:最直接的方法,每次读取都重新用 open() 打开。

    with open('test.txt', 'r') as f:
        lines1 = f.readlines()
    with open('test.txt', 'r') as f:
        lines2 = f.readlines() # 现在 lines2 又有数据了
    
  2. 将内容保存到变量:如果文件不大,第一次读取后把内容(比如列表 lines)存下来,后面直接复用这个变量,不需要重新读文件。

  3. 移动文件指针:使用 f.seek(0) 将指针移回文件开头,然后就可以再次读取了。

    with open('test.txt', 'r') as f:
        lines1 = f.readlines()
        f.seek(0) # 指针回到开头
        lines2 = f.readlines() # 现在 lines2 也有数据了
    

总结:文件对象是一次性消耗品,读完记得重置指针或重新打开。

我知道了,文件指针的问题,被移动到结尾了。谢谢。readlines 前 project_file.seek(0, 0)就好了

回到顶部