zoukankan      html  css  js  c++  java
  • 用Python对体积较大的CSV文件进行比较的经验

    用Python对体积较大的CSV文件进行比较的经验 » 进化的测试 | 进化的测试

    032010
     

    最近的工作总是跟数据打交道,需要经常比较一些CSV文件,这些CSV文件其实都需要被LOAD到数据库里面,所以也就是一堆堆的数据文件需要比较。暂时没有发现有比较好用的现成的CSV比较工具,自己动手用Python做了一个凑合能用的。思想比较简单,就是把CSV文件的内容读取出来,保存为一个list,然后把2个CSV文件所生成的list进行对比。有个特殊的需求,就是对于CSV文件中一些肯定不一样的列,例如process date这样的字段,是需要跳过的。由于本地生成的CSV文件比较小,刚开始没有注意到如果文件太大的话会占用很多的内存。最开始的版本是:

    def readcsv2list(filename, rows):
        fileobj = open(filename, 'rb')
        csvreader = csv.reader(fileobj)
        retlist = []
        for row in csvreader:
            clist = []
            selected_rows = [ic for ic in range(len(row)) if ic not in rows]
            for c in selected_rows:
                clist.append(row[c])
            retlist.append(clist)
     
        fileobj.close()
        return retlist

    后来用这个脚本比较生产环境数据的时候就遇到问题了,其中最大的一个数据文件大概是1.5GB,这只是文件大小,把文件转成list以后所占用的内存会翻几倍(这个很容易理解,整数1在文件里面站1个字节,放到list里面就要4个字节了)。一下子把机器的内存用光了。随后找了一下文档,csv.reader是没有一个方法可以指定一次读取若干行数据的。后来就利用file object有一个readline()方法,通过一个参数来控制一次读取多少行的记录,从而达到控制内存使用量的目的。需要的注意的点有:1. 在读完若干行数据以后,需要获取一下当前这个file object的位置,Python提供了.tell()方法来获取这个值;2. 读取文件的时候需要知道上一会读到什么地方了,并且从那里继续往下读,用到了.seek()方法;3. readline()方法在读到文件末尾的时候只会返回一个空字符,所以需要对这个空字符做一点处理。

    def readcsv2list(filename, rows, last_position, max_line):
        fileobj = open(filename, 'rb')
        fileobj.seek(last_position)
        datalines = []
        for i in range(max_line):
            line_itme = fileobj.readline()
            if len(line_itme) > 0:
                datalines.append(line_itme)
            else:
                break
     
        csvreader = csv.reader(datalines)
        retlist = []
        for row in csvreader:
            clist = []
            selected_rows = [ic for ic in range(len(row)) if ic not in rows]
            for c in selected_rows:
                clist.append(row[c])
            retlist.append(clist)
     
        current_position = fileobj.tell()
        fileobj.close()
        return retlist, current_position

    Python,尤其是低版本(例如我们用的2.4.3),对于在程序里面显式地del一些变量(通常是个大list之类),是不会立刻释放内存的,所以对于处理数据量比较大的case的时候就需要特别注意内存的使用。参考文章:
    Python Memory Management
    Why doesn’t Python release the memory when I delete a large object?

  • 相关阅读:
    【Lintcode】112.Remove Duplicates from Sorted List
    【Lintcode】087.Remove Node in Binary Search Tree
    【Lintcode】011.Search Range in Binary Search Tree
    【Lintcode】095.Validate Binary Search Tree
    【Lintcode】069.Binary Tree Level Order Traversal
    【Lintcode】088.Lowest Common Ancestor
    【Lintcode】094.Binary Tree Maximum Path Sum
    【算法总结】二叉树
    库(静态库和动态库)
    从尾到头打印链表
  • 原文地址:https://www.cnblogs.com/lexus/p/3325530.html
Copyright © 2011-2022 走看看