Python:多处理的pickle错误

时间:2015-06-25 04:14:53

标签: python multiprocessing pickle

如下所示,我已将代码更改为使用池。我还简化了我的功能,并在下面包含了我的所有代码。但是,现在我收到了一个不同的错误:NameError:全局名称' split_files'未定义

我想要做的是将实际的文件块传递给parse_csv_chunk函数,但我不知道该怎么做。

import csv
from itertools import islice
from collections import deque
import time
import math
import multiprocessing as mp
import os
import sys
import tempfile

csv_filename = 'test.csv'

def parse_csv_chunk(files_index):
    global split_files
    print files_index
    print len(split_files)
    return 1

def split(infilename, num_chunks):
    READ_BUFFER = 2**13
    in_file_size = os.path.getsize(infilename)
    print 'Original file size:', in_file_size
    chunk_size = in_file_size // num_chunks
    print 'Target chunk size:', chunk_size
    print 'Target number of chunks:', num_chunks
    files = []
    with open(infilename, 'rb', READ_BUFFER) as infile:
        infile.next()
        infile.next()
        infile.next()
        for _ in xrange(num_chunks):
            temp_file = tempfile.TemporaryFile()
            while temp_file.tell() < chunk_size:
                try:
                    #write 3 lines before checking if still < chunk_size
                    #this is done to improve performance
                    #the result is that each chunk will not be exactly the same size
                    temp_file.write(infile.next())
                    temp_file.write(infile.next())
                    temp_file.write(infile.next())
                #end of original file
                except StopIteration:
                    break
            #rewind each chunk
            temp_file.seek(0)
            files.append(temp_file)
    return files

if __name__ == '__main__':
    start = time.time()
    num_chunks = mp.cpu_count()
    split_files = split(csv_filename, num_chunks)
    print 'Number of files after splitting: ', len(split_files)

    pool = mp.Pool(processes = num_chunks)
    results = [pool.apply_async(parse_csv_chunk, args=(x,)) for x in range(num_chunks)]
    output = [p.get() for p in results]
    print output

我试图将csv文件拆分为多个部分并让它们由我的每个CPU内核处理。这就是我到目前为止所做的:

import csv
from itertools import islice
from collections import deque
import time
import math
import multiprocessing as mp
import os
import sys
import tempfile

def parse_csv_chunk(infile):
    #code here
    return

def split(infilename, num_chunks):
    #code here
    return files

def get_header_indices(infilename):
    #code here
    return

if __name__ == '__main__':
    start = time.time() #start measuring performance
    num_chunks = mp.cpu_count() #record number of CPU cores
    files = split(csv_filename, num_chunks) #split csv file into a number equal of CPU cores and store as list
    print 'number of files after splitting: ', len(files)
    get_header_indices(csv_filename) #get headers of csv file
    print headers_list

    processes = [mp.Process(target=parse_csv_chunk, 
       args=ifile) for ifile in enumerate(files)] #create a list of processes for each file chunk

    for p in processes:
        p.start()

    for p in processes:
        p.join()

    end = time.time()

    print "Execution time: %.2f" % (end - start) #display performance

该行&#39; p.start()&#39;似乎存在问题。我在控制台上看到了很多输出,最终表明存在错误:

pickle.PicklingError: Can't pickle <built-in method write of file object at 0x02
22EAC8>: it's not found as __main__.write

我没有包含我调用的函数的代码,因为它们很长,但我可以根据需要。我想知道我是否正确使用多处理。

1 个答案:

答案 0 :(得分:0)

首先,如果您没有使用Pool的{​​{1}}和imap方法?

其次,在没有看到代码的情况下很难说出任何细节,特别是因为错误指向了未提供的部分代码。

但是,您似乎正在使用Pool正确使用的内容 - 这是一个序列化问题。

请注意,如果您使用multiprocessing,则可以序列化dill方法。

write

>>> import dill >>> >>> f = open('foo.bar', 'w') >>> dill.dumps(f.write) '\x80\x02cdill.dill\n_get_attr\nq\x00cdill.dill\n_create_filehandle\nq\x01(U\x07foo.barq\x02U\x01wq\x03K\x00\x89c__builtin__\nopen\nq\x04\x89K\x00U\x00q\x05tq\x06Rq\x07U\x05writeq\x08\x86q\tRq\n.' 的大多数版本使用multiprocessing(或使用C版本构建的cPickle版本),而pickle可以将其类型注入python版本dill,它不能在C等价物中这样做。

有一个pickle - dill的激活分叉 - 所以你可以尝试一下,好像它纯粹是一个酸洗问题,那么你应该通过multiprocessing来解决它。 / p>

请参阅:https://github.com/uqfoundation/multiprocess

编辑(OP更新后):助手功能中的multiprocess声明不能与global一起使用。为什么不使用有效载荷函数(如pickle)读取文件的一部分并返回内容,或写入目标文件?不要返回文件列表。我知道它们是split个对象,但除非你使用TemporaryFile(即使那时它很敏感)你也不能腌制文件。如果您必须,请返回文件名,而不是文件,并且不要使用dillTemporaryFile会阻止尝试传递文件。因此,您应该重构代码,或者按照我之前的建议,尝试使用pickle(使用multiprocess)来查看是否可以绕过序列化问题。

相关问题