如下所示,我已将代码更改为使用池。我还简化了我的功能,并在下面包含了我的所有代码。但是,现在我收到了一个不同的错误: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
我没有包含我调用的函数的代码,因为它们很长,但我可以根据需要。我想知道我是否正确使用多处理。
答案 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
(即使那时它很敏感)你也不能腌制文件。如果您必须,请返回文件名,而不是文件,并且不要使用dill
。 TemporaryFile
会阻止尝试传递文件。因此,您应该重构代码,或者按照我之前的建议,尝试使用pickle
(使用multiprocess
)来查看是否可以绕过序列化问题。