Python读取文件、大文件和指定行内容的几种方法

发表时间:2019-10-17 23:11 | 分类:Python | 浏览:5,483 次

在使用python处理文本的时候,经常会需要读取文件的内容。如果文件比较小,那么直接使用open文件对象打开文件,再通过read()方法最为方便,这种方法就是把文件内容读出来后放到内存变量。

read

f = open('/var/log/nginx/zhangnq.com.log','rb')
#读取全部
log_data = f.read()
f.close()
# 按行读取

但是,当文件很大比如10GB,这种方法就会撑爆内存,爆出类似memoryError的错误。所以,要保险起见,可以反复调用read(size)方法,每次最多读取size个字节的内容。

如果是处理连续文本内容,文件对象还支持readline()和readlines()两个方法。不同的是readline()没执行一次读取一行,readlines()会把所有内容都读出来。所以readlines方法不适用大文件。

readline

import time
f = open('/var/log/nginx/zhangnq.com.log','rb')
while True:
    print(f.readline())
    time.sleep(1)

内存使用:占用不到4兆。

python_file_readline

readlines

import time
f = open('/var/log/nginx/zhangnq.com.log','rb')
for line in f.readlines():
    print(line)
    time.sleep(1)

内存使用:内存占用50多兆。

python_file_readlines

分块读取

那么另外一个比较好的办法是把大文件分块,这里用到python迭代器yield。

# 读取大文件
def read_in_chunks(file_path, chunk_size=1024*1024):
    """
    Lazy function (generator) to read a file piece by piece.
    Default chunk size: 1M
    You can set your own chunk size
    """
    file_object = open(file_path)
    while True:
        chunk_data = file_object.read(chunk_size)
        if not chunk_data:
            break
        yield chunk_data

默认一次读取1兆大小的内容。

with open

另外找到一个办法。可以用with语句打开和关闭文件,包括抛出一个内部块异常。for line in f文件对象f视为一个迭代器,会自动的采用缓冲IO和内存管理,所以你不必担心大文件。

with open(...) as f:
  for line in f:
    process(line) # 

读取指定行内容

对于小文件,最简单是用readlines方法读取文件内容到列表,然后再使用列表和分片。

f = open('/var/log/nginx/zhangnq.com.log','rb')
data = f.readlines()
# 读取 第一行到第十行内容
print(data[0:10])

如果是大文件,可行的方法是先分块读取文件,然后再把指定行内容保存下来。不过这个办法有个小问题,被分块的那行内容取不全,而且效率不高。
例如:

# 读取文件多行间内容
def read_file_lines(file_path, line_start=1, line_end=-1):
    content_list = list()
    i = 1
    for chunk in read_in_chunks(file_path, 1024*1024*10):
        for tmp in chunk.split('\n'):
            if line_end != -1:
                if i >= line_start and i <= line_end:                     content_list.append(tmp)             else:                 if i >= line_start:
                    content_list.append(tmp)
            i += 1
    return content_list

有更好的办法欢迎交流。

本文标签:

本文链接:https://www.sijitao.net/3146.html

欢迎您在本博客中留下评论,如需转载原创文章请注明出处,谢谢!

已经有2个回复
Comment (2)
Trackbacks (0)
  1. 夏日博客  ( 2019.10.18 19:16 ) : #-9

    Python感觉比PHP还是难。

  2. 头条  ( 2019.10.29 00:01 ) : #-8

    文章不错支持一下吧

  1. 还没有Trackbacks
一键脚本 博客历程 留言联系 文章归档 网站地图 谷歌地图
Copyright © 2010-2024 章郎虫博客 All Rights Reserved.