我需要处理一个包含很多工作表的Excel,但是每个工作表都有大数据。如果使用openpyxl加载这个excel,那将花费大量时间,所以我想通过多进程分析每个工作表。 / p>
这样的简短代码:
import multiprocessing as mp
import openpyxl
def LoadEx():
wb=openpyxl.load_workbook('example.xlsx')
sheetnames=wb.get_sheet_names()
return sheetnames, wb
def job(sheet,wb):
gs=wb.get_sheet_by_name(sheet)
for i in range(10):
if gs.cell(row=i,column=2).value=='Target':
gs.cell(row=i,column=3).value='OK'
if __name__=='__main__':
sheetnames,wb=LoadEx()
pool=mp.Pool()
for sheetname in sheetnames:
res=pool.apply_async(job, (sheetname,wb))
pool.close()
pool.join()
wb.save('example_output.xlsx')
但是,文件'example_output.xlsx'似乎没有保存job()的结果, 在这种情况下,我该如何获得多进程的效果? 可能有人可以帮助我,思考
答案 0 :(得分:1)
您可以使用multiprocessing
执行此操作,但您必须支付。
global wb
成为您使用的每个process
的副本。
因此,使用4 processes
,您的内存必须足够大,才能容纳4个工作簿副本。
鉴于wb
是副本,您的更改属于此副本。
您必须将更改复制到一个工作簿中。
复制工作表可能非常耗时。
为了克服酸洗错误,我从排队ws
变为wsDiff
。
而不是写入ws
副本,将更改聚合到wsDiff
。
作为奖励,复制到目标wb
会更快。
时间表:cpu_count = 2,10个工作表,工作量:
def ws_job(...
Job Processes without mp 2 4
Time 0:00:21.260746 0:00:10.214942 0:00:07.097369
此工作示例适用于给定的问题def job
。
,例如:
import multiprocessing as mp
import queue, os, time
import random as rd
import openpyxl
class wsDiff(object):
def __init__(self, row, column, value):
self.row = row
self.column = column
self.value = value
def ws_job(wb, ws_idx):
ws = wb.worksheets[ws_idx]
print('pid %s: process (%s)' % (os.getpid(), ws.title))
# *** DO SOME STUFF HERE***
# Simulate workload
time.sleep(rd.randrange(1, 4))
diff = []
for i in range(1, 11):
if ws.cell(row=i, column=2).value == 'Target':
#ws.cell(row=i, column=3).value = 'OK'
diff.append( wsDiff(i, 3, 'OK') )
return diff
def job(fq, q, wb):
while True:
try:
ws_idx = fq.get_nowait()
except queue.Empty:
print('pid %s: exit job' % os.getpid())
exit(0)
q.put((ws_job(wb, ws_idx), ws_idx))
time.sleep(0.1)
def writer(q, wb):
print('start writer_handler')
while True:
try:
diff, i_ws = q.get()
except ValueError:
print('writer ValueError exit(1)')
exit(1)
if diff == None:
wb.save('../test/example_output.xlsx')
exit(0)
ws = wb.worksheets[i_ws]
print('pid %s: update sheet %s from diff' % (os.getpid(), ws.title))
for d in diff:
ws.cell(row=d.row, column=d.column).value = d.value
def mpRun():
wb = openpyxl.load_workbook('../test/example.xlsx')
f_q = mp.Queue()
for i in range(len(wb.worksheets)):
f_q.put(i)
w_q = mp.Queue()
w_p = mp.Process(target=writer, args=(w_q, wb))
w_p.start()
time.sleep(0.1)
pool = [mp.Process(target=job, args=(f_q, w_q, wb)) for p in range(os.cpu_count() + 2)]
for p in pool:
p.start()
time.sleep(0.1)
for p in pool:
p.join()
time.sleep(0.2)
# Terminate Process w_p after all Sheets done
w_q.put((None, None))
w_p.join()
print('EXIT __main__')
使用Python测试:3.4.2 - openpyxl:2.4.1 - LibreOffice:4.3.3.2
答案 1 :(得分:0)
不幸的是,Workbooks不适合多处理,因为有很多共享状态。