使用Python 递归合并不同目录下小文件

来源:互联网 发布:影视播放软件 编辑:程序博客网 时间:2024/05/17 04:25

背景

项目中, 由网络爬虫爬取的日志文件, 需要导入到 hive 数据仓库中, 但日志文件包含很多的小文件, 散落在许多子文件夹下.

总所周知, 当 hive 的输入端如果由许多小文件组成的话, 每个小文件都会启动一个 map 任务, 如果文件多而小, 会造成 map 任务启动和初始化的时间远大于逻辑处理的时间, 造成数据处理时间大大增加, 甚至会造成 OOM的后果.

鉴于此, 当我们执行一个hive任务时, 当发现数据量不大, 但任务数巨多时, 就要考虑是不是小文件在作祟. 如果是, 请在 Map 前进行输入的合并.

hive 通过设置启动参数的方式, 社区有很多文章介绍, 这里引用一下这篇文章:
Hive小文件合并

以下主要介绍编程方式合并.

代码

话不多少, 直接上 python 代码:

#!/usr/bin/python# -*- coding:utf8 -*-import osallFileNum = 0def 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 fileif __name__ == '__main__':    merge_small_file(1, '/Users/david/Downloads/dong_bao_output/')    print 'Files in total =', allFileNum
0 0