Python大文件的处理

由问题引入:如果文件过大,大到内存无法缓冲数据,一次性读取所有内容就会出现memoryError或者是IOError.

拷贝文件(考虑到大文件的问题)
import os

# 大文件的读写操作
# 实现文件的拷贝功能,需要考虑大文件的操作
def copy_file(src_path, dst_path):
    # 判断源文件和目标文件路径是否相同
    if os.path.abspath(src_path) == os.path.abspath(dst_path):
        return
    # 判断源文件是否是文件
    if not os.path.isfile(src_path):
        return
    if os.path.isdir(dst_path):
        # 如果目标路径是目录的话,则将文件复制到目录下
        dst_path = os.path.join(dst_path, os.path.basename(src_path))

    # 设置每次读取的固定长度
    length = 16 * 1024
    with open(src_path, 'rb') as fsrc:
        with open(dst_path, 'wb') as fdst:
            while True:
                buf = fsrc.read(length)
                if not buf:
                    break
                fdst.write(buf)
# 测试
# 当前文件下的flydb.json复制到copy_d目录下
src = os.path.join(r'./', 'flydb.json')
dst = os.path.join(r'./copy_db')
copy_file(src, dst)

这种处理大文件的方式是每次读取到一定长度的文件(给read方法设置参数来设置文件对象的读取长度)内容进行处理。
上面的需求使用文件对象的read方法实现的,这个方法如果不指定参数,会一次性读取文件的全部内容。

有时候我们使用readlines比较方便,该方法返回是每一行数据组成的列表,比如要读取的是配置文件。
readlines这个方法如果不指定参数,也是会一次性读取文件的全部内容。

我们知道文件对象是一个迭代器,对文件对象进行for in遍历的时候,解决大文件读取问题,正是依赖了迭代器的lazy特性。

with open(path, 'r+') as fp:	
	 for line in fp:
	 	# 处理读取的行数据
	 	processor(line)

我们将上面的文件的读取封装成一个迭代器,方便外部调用这个迭代器。

def get_lines():
	with open('test.txt', 'rb+') as fp:
		for line in fp:
			yield line
	
if __name__ == '__main__':
	for line in get_lines():
		print line

看一下下面这个提问,为了解决使用for line in fp读取文件速度很慢的问题,问题回答者探讨了多种情况下的解决方案,在I/O密集型的前提下,可以探寻一下的解决方案:
https://stackoverflow.com/questions/30294146/python-fastest-way-to-process-large-file

网上看到了这个尝试,先代码转载下来:实际的效果和使用还有待验证!

from mmap import mmap


def get_lines(fp):
    with open(fp,"r+") as f:
        m = mmap(f.fileno(), 0)
        tmp = 0
        for i, char in enumerate(m):
            if char==b"\n":
                yield m[tmp:i+1].decode()
                tmp = i+1

if __name__=="__main__":
    for i in get_lines("fp_some_huge_file"):
        print(i)

你可能感兴趣的:(Python)