用Python對體積較大的CSV文件進行比較的經驗 » 進化的測試 | 進化的測試javascript
八 03 2010最近的工做老是跟數據打交道,須要常常比較一些CSV文件,這些CSV文件其實都須要被LOAD到數據庫裏面,因此也就是一堆堆的數據文件須要比較。暫時沒有發現有比較好用的現成的CSV比較工具,本身動手用Python作了一個湊合能用的。思想比較簡單,就是把CSV文件的內容讀取出來,保存爲一個list,而後把2個CSV文件所生成的list進行對比。有個特殊的需求,就是對於CSV文件中一些確定不同的列,例如process date這樣的字段,是須要跳過的。因爲本地生成的CSV文件比較小,剛開始沒有注意到若是文件太大的話會佔用不少的內存。最開始的版本是:html
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()方法在讀到文件末尾的時候只會返回一個空字符,因此須要對這個空字符作一點處理。java
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_positionPython,尤爲是低版本(例如咱們用的2.4.3),對於在程序裏面顯式地del一些變量(一般是個大list之類),是不會馬上釋放內存的,因此對於處理數據量比較大的case的時候就須要特別注意內存的使用。參考文章:
Python Memory Management
Why doesn’t Python release the memory when I delete a large object?python