Python多处理与熊猫占用全部内存并被杀死

时间:2017-12-15 11:58:58

标签: python pandas csv multiprocessing python-multiprocessing

我有6个平均10G大小的csv文件

我通过shell 1为每个文件运行6个进程(xargs)

merchants () {
    echo -n merchant_1 merchant_2 merchant_2 merchant_4 merchnat_5 merchant_6
}
merchants | xargs -L1 -P6 -d' ' -I{} bash -c \"python main.py '{}' || true\

我的代码有以下流程。 (1个文件)

  • 启动一个包含2个进程的池#(所以对于6个文件= 12个进程)
  • 在块(pandas)(200,000)行中读取csv。 #1 chunk avg = 2gb(所以12 processes = 24gb)
  • 将此块传递给pool.async(process, (df, transformer, output_filename))

process函数接受数据帧,创建一个变换器对象(变换器是一个有12-15种方法的类。每个方法负责执行转换(例如删除某些黑名单单词,重命名列,小写等) )然后返回转换后的数据帧。然后将数据帧写入新的csv文件。结果我获得了多个新的csv文件(每行200,000行)

现在的问题是内存使用情况。

按照上面的计算,应该使用24gb(已经有一点缓冲区)。

该机器有64 gb的内存和32个处理器。由于我运行多处理,我看到流程运行从10-20到htop不等。

但是它会逐渐增加内存并达到整个60GB内存并且每件事都会被杀死。有两个可能的原因导致这种高内存使用。

  1. 我的代码在转换逻辑中存在一些问题(我不会这样做 见到现在)
  2. 我使用多重处理的机制不正确。
  3. 以下是相关代码

    transformer = globals()[merchant['transformer']] # i take the class name from configuration file
                pool = Pool(processes=merchant['num_of_process']) # 2
                chunk_index = 1
    
                for df in pd.read_csv(downloaded_file, chunksize=chunksize, compression='gzip', skipinitialspace=True, encoding='utf-8'):
                    output_file_name = output_path + \
                        merchant['output_file_format'].format(
                            file_index, chunk_index)
                    pool.apply_async(process, (df, transformer, output_file_name))
                    chunk_index += 1
    

    处理

    def process(df, transformer, output_file_name):
        """
        Process the csv chunk in a separate thread
            :param df:
            :param transformer:
            :param file_index:
            :param chunk_index:
        """
        with TransformerContext(transformer(df)) as transformer:
            methods = [method for method in dir(transformer) if callable(
                getattr(transformer, method)) if not method.startswith('_')]
            for method in methods:
                getattr(transformer, method)()
        handle = open(output_file_name, "w")
        transformer.df.to_csv(output_file_name, index=False,
                              compression='gzip', sep='\t', quoting=1, encoding='utf-8')
        del df
        del transformer
        handle.close()
    
        return True
    

    我在这里使用上下文的原因是我想在写入csv之前删除不必要的列。由于它必须运行不同类型的文件,因此它将作为通用代码。

    class TransformerContext:
        def __init__(self, transformer):
            self.transformer = transformer
            self.original_columns = list(transformer.df.columns)
    
        def __enter__(self):
            return self.transformer
    
        def __exit__(self, exc_type, exc_val, exc_tb):
            processed_columns = list(self.transformer.df.columns)
            for column in self.original_columns:
                if column in processed_columns:
                    del self.transformer.df[column]
    

    如果这里有与多处理相关的内容,我需要帮助识别/修复。如果没有,那么我将去检查我的逻辑代码。

    由于

0 个答案:

没有答案
相关问题