1. 程式人生 > >使用Python 遞迴合併不同目錄下小檔案

使用Python 遞迴合併不同目錄下小檔案

背景

專案中, 由網路爬蟲爬取的日誌檔案, 需要匯入到 hive 資料倉庫中, 但日誌檔案包含很多的小檔案, 散落在許多子資料夾下.

總所周知, 當 hive 的輸入端如果由許多小檔案組成的話, 每個小檔案都會啟動一個 map 任務, 如果檔案多而小, 會造成 map 任務啟動和初始化的時間遠大於邏輯處理的時間, 造成資料處理時間大大增加, 甚至會造成 OOM的後果.

鑑於此, 當我們執行一個hive任務時, 當發現數據量不大, 但任務數巨多時, 就要考慮是不是小檔案在作祟. 如果是, 請在 Map 前進行輸入的合併.

hive 通過設定啟動引數的方式, 社群有很多文章介紹, 這裡引用一下這篇文章:

Hive小檔案合併

以下主要介紹程式設計方式合併.

程式碼

話不多少, 直接上 python 程式碼:

#!/usr/bin/python
# -*- coding:utf8 -*-

import os
allFileNum = 0
def merge_small_file(level, path):
    global allFileNum

    '''''
    列印一個目錄下的所有資料夾和檔案
    '''
    # 所有資料夾,第一個欄位是次目錄的級別
    dirList = []
    # 所有檔案
    fileList = []
    # 返回一個列表,其中包含在目錄條目的名稱(google翻譯)
files = os.listdir(path) # 先新增目錄級別 dirList.append(str(level)) for f in files: targetFile = "/data/admin/dong_bao_spider/merge_json_files.json" output_json_file = open(targetFile,'a') if(os.path.isdir(path + '/' + f)): # 排除隱藏資料夾。因為隱藏資料夾過多 if
(f[0] == '.'): pass else: # 新增非隱藏資料夾 dirList.append(f) getJsonFilePath(level, path+'/'+f) if(os.path.isfile(path + '/' + f)): # 判斷檔案是以".json"結尾的 if str(f).endswith('.json'): # 新增檔案 fileList.append(path + '/' + f) allFileNum += 1 with open(str(path + '/' + f)) as input_json_file: for r in input_json_file.readlines(): # 去掉每一行後面的換行符,先加換行符 output_json_file.write(r.strip('\n') + '\n') output_json_file.close() # 以下程式碼為演示程式掃描過的資料夾, 分層顯示 # 當一個標誌使用,資料夾列表第一個級別不列印 # i_dl = 0 # for dl in dirList: # if(i_dl == 0): # i_dl = i_dl + 1 # else: # # 列印至控制檯,不是第一個的目錄 # print '-' * (int(dirList[0])), dl # # 列印目錄下的所有資料夾和檔案,目錄級別+1 # printPath((int(dirList[0]) + 1), path + '/' + dl) # for fl in fileList: # if str(fl).endswith(".json"): # # 列印檔案 # print '-' * (int(dirList[0])), fl # # 隨便計算一下有多少個檔案 # allFileNum = allFileNum + 1 # for file in fileList: # print file if __name__ == '__main__': merge_small_file(1, '/Users/david/Downloads/dong_bao_output/') print 'Files in total =', allFileNum