如何在OpenPYXL对象中使用多进程? [英] How to use multiprocess in openpyxl object?
本文介绍了如何在OpenPYXL对象中使用多进程?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
我需要处理一个有很多工作表的EXCEL,但每个工作表都有很大的数据量,如果使用Openpyxl来加载这个EXCEL,会花费很多时间,所以我想对每个工作表进行多进程分析。
简短代码如下:
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’似乎没有保存作业()的结果,
在这种情况下,如何获得多进程的效果?
希望有人能帮我,想
推荐答案
您可以使用multiprocessing
操作,但您必须付费。
global wb
成为您使用的每个process
的副本。 因此,使用4processes
时,您的内存必须足够容纳4份工作簿。由于
wb
是副本,您的更改属于此副本。 您必须将更改复制到一个工作簿中。 复制工作表可能很耗时。
为了克服酸洗错误,我将排队从ws
改为wsDiff
。
不是写入ws
副本,而是汇总对wsDiff
的更改。
另外,复制到目标wb
会更快。
时间表:cpucount=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
这篇关于如何在OpenPYXL对象中使用多进程?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
查看全文