python算法之归并算法-使用readline而不是用readlines文件合并

问题:

最近处理公司某系统的日志,但是日志文件太多,而且量很大(使用 du -sh查看了一下有几百G),直接一次性将全部日志数据处理完会导致服务器负载很高,内存几乎被吃光了,进程经常被管理员kill


处理方法

采用分天处理文件,然后将当前的和前一天的文件合并的方法,大大提供了程序效率,而且降低了内存占用。涉及到的关键代码就是文件合并,使用归并算法来将文件合并


实现思路:

    1、首先从日志里面分天提取需要要的数据,并排序输出到文件,因为归并算法处理的是两个已排好序的数据结

    2、然后将当前天的日志和前一天的日志合并。file_old代表前一天合并后的日志数据文件 ,file_today代表提取出来的前一天日志数据文件 、file_merge代表合并后的当前日志数据文件 ,也就是要将当天的日志文件和前一天合并后的日志文件进行合并,并输出到file_merge作为下一个迭代的输入。

    3、归并(Merge)排序是将两个(或两个以上)有序表合并成一个新的有序表,即把待排序序列分为若干个有序的子序列,再把有序的子序列合并为整体有序序列。

         主要步骤:a、两个指针x , y,分别指向两个已排序的序列的开头

                           b、比较两个指针所指向的元素x ,y ,选择相对小的元素放入到合并空间,并移动指针到下一位置

                           c、重复步骤3直到某一指针超出序列尾

                           d、将另一序列剩下的所有元素直接复制到合并序列尾

下面的代码假设提取出来的数据是以空格分隔的,每一行的第一个数据是关键字key,用作排序的,如果关键字相同,则根据业务逻辑合并这一行。第20行的 mergeLine(old,today) 是key相同的时候根据业务逻辑处理数据的方法,可以根据自己的需求写。


文件归并算法代码

def mergeFile(file_old,file_today,file_merge):
    fp_old = open(file_old,"r")
    fp_today = open(file_today,"r")
    fp_merge = open(file_merge,"w")

    old_line = fp_old.readline()
    today_line = fp_today.readline()
    
    while old_line and today_line:
        old = old_line.strip().split()
        today = today_line.strip().split()

        if old[0] < today[0]:
            fp_merge.write(old_line)
            old_line = fp_old.readline()
        elif old[0] > today[0]:
            fp_merge.write(today_line)
            today_line = fp_today.readline()
        else:     
            megre_line = mergeLine(old,today)
            fp_merge.write(megre_line)
            old_line = fp_old.readline()
            today_line = fp_today.readline()
            continue
        
    if old_line:
        fp_merge.write(old_line)
        for line in fp_old:
            fp_merge.write(line)
    if today_line:
        fp_merge.write(today_line)
        for line in fp_today:
            fp_merge.write(line)  
            
    fp_merge.close()
    fp_old.close()
    fp_today.close()

这里采用 readline 逐行读取文件,一行一行处理,这样占用内存很低。

由于每天的日志数据文件小的也有1G,大的有4、5G,直接使用readlines()读取全部文件会吃很多内存。

也可以使用linecache.getlines 将文件读入缓存,然后使用 linecache.getline(i) 来读取指定行。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值