我正在制作一个解析数据文件的python。然后将解析的数据发送到excel文件。 数据可能相当庞大。我正在看10到20列,但行数可以超过100.000。
使用win32com将此数据量写入excel需要相当长的时间。我的第一步是在excel文件中迭代遍历单元格,这非常耗时。经过一番挖掘后,我发现如何通过一次调用来编写一行,从而大大减少了所需的时间。
但是,当我需要向Excel发送100.000行数据时,仍然需要花费很多时间。我很确定通过一次调用发送完整的数组,我可以进一步提高速度。但是到目前为止我无法做到这一点。
请参阅下面的代码,该代码演示了此问题。代码显示了时间上的差异。但是,第三步,通过单个调用向一个范围发送完整数组不会导致excel中的正确数据。我做错了什么?
import win32com.client
import time
#create data array
row = range(0,10)
i = 0
data_array = []
while i < 1000:
data_array.append(row)
i += 1
#write the array to an excel file
excel = win32com.client.Dispatch("Excel.Application")
excel.Visible = True
excel.ScreenUpdating = False
book = excel.Workbooks.Add()
sh1 = book.Worksheets(1)
sh2 = book.Worksheets(2)
sh3 = book.Worksheets(3)
#double loop, writing individual cells
print "Writing with double loop to inidividual cells."
start = time.time()
row = 0
for line in data_array:
row += 1
col = 0
for field in line:
col += 1
sh1.Cells(row, col).Value = field
print "Processing time: " + str(time.time() - start) + " seconds."
#single loop, writing a row to a range
print "Writing with double loop to inidividual cells."
start = time.time()
row = 0
for line in data_array:
row += 1
sh2.Range(sh2.Cells(row,1), sh2.Cells(row, len(line))).Value = line
print "Processing time: " + str(time.time() - start) + " seconds."
#no loop, write array to range
print "Writing with double loop to inidividual cells."
start = time.time()
try:
sh3.Range(sh3.Cells(row,1), sh3.Cells(len(data_array), len(data_array[0]))).Value = data_array
print "Processing time: " + str(time.time() - start) + " seconds."
except:
print "Failed to write array to excel file."
excel.ScreenUpdating = True
sheet = None
book = None
excel.Quit()
excel = None
答案 0 :(得分:4)
我一直在研究这个问题。并且已经得出了一些有趣的结论。
确实有多种解决方案可以将数据从python写入excel。我最终专注于三个模块。
<强> win32com.client 强>
工作缓慢。但是文档可以在excel中打开。因此,最终结果可供excel中的用户开始使用。不适合大量数据。
在我的计算机(核心i5)app上编写10,000行10列。 70秒。
import win32com.client
import time
#create data array
row = range(0,10)
i = 0
data_array = []
while i < 10000:
data_array.append(row)
i += 1
#write the array to an excel file
excel = win32com.client.Dispatch("Excel.Application")
excel.Visible = True
excel.ScreenUpdating = False
book = excel.Workbooks.Add()
sheet = book.Worksheets(1)
#single loop, writing a row to a range
print "Writing using win32com.client"
start = time.time()
row = 0
for line in data_array:
row += 1
sheet.Range(sheet.Cells(row,1), sheet.Cells(row, len(line))).Value = line
print "Processing time: " + str(time.time() - start) + " seconds."
print "Completed: " + str(time.time() - start) + " seconds."
excel.ScreenUpdating = True
sheet = None
book = None
excel.Quit()
excel = None
<强> openpyxl 强>
有点快,但仍然不是很好。此模块在将数据传输到Excel内存对象时速度很慢,但保存速度非常快。它在22.3秒内创建10,000行10列,并在另外0.5秒内保存文件。 当我用100,000行和10列测试时。数据在228.3秒内创建,保存文件在另外2.9秒内完成。相当慢,但文件保存速度很快。因此openpyxl可能适合对现有数据进行更改(格式化),尽管我还没有对此进行测试。 另一个优点是使用win32com.client进行使用openpyxl编码更容易。
import openpyxl
import sys
import time
#create data array
row = range(0,10)
i = 0
data_array = []
while i < 10000:
data_array.append(row)
i += 1
#create an excel workbook and sheet object
book = openpyxl.Workbook(optimized_write = True)
#single loop, writing rows
start = time.time()
print "Writing with single loop using openpyxl"
sheet = book.create_sheet()
for line in data_array:
sheet.append(line)
print "Processing time: " + str(time.time() - start) + " seconds."
#close and save the file.
book.save('openpyxl.xlsx')
print "Total time: " + str(time.time() - start) + " seconds."
我正面临着openpyxl的另一个问题。在我的真实工具中,openpyxl在保存大量数据(> 10,000行)方面存在问题。我还没想到,也许我不想再深入了解它。
<强> PyExcelerate 强>
这首先是快速的。它在0.17秒内创建了10,000行和10列。但是保存文件需要2.2秒。到目前为止三者中最快的选择。 当我尝试使用此模块保存100,000行和10列时,excel数据仅在1.8秒内创建。但是现在保存文件需要21.7秒。 因此,这个模块非常快,但写文件会受到惩罚。整体而言仍然是最快的。 PyExcelerate的另一个优点是编码非常简单,再次像openpyxl一样容易。
import pyexcelerate
import sys
import time
#create data array
row = range(0,10)
i = 0
data_array = []
while i < 10000:
data_array.append(row)
i += 1
print sys.version
#create an excel workbook and sheet object
book = pyexcelerate.Workbook()
#single loop, writing rows
start = time.time()
print "Writing with single loop using PyExcelerate"
book.new_sheet("data", data = data_array)
print "Processing time: " + str(time.time() - start) + " seconds."
#close and save the file.
book.save('pyexcelerate.xlsx')
print "Total time: " + str(time.time() - start) + " seconds."
所以我的结论是PyExcelerate是迄今为止最快的。 win32com.client的优点是创建的excel文件可以在excel中打开,以使创建的数据可供用户开始使用它。在创建样式后,Openpyxl可能很有趣。但是,我还没有测试过这个。 因此,在一个应用程序中组合win32com.client,openpyxl和PyExcelerate可能是有益的。
答案 1 :(得分:3)
使用COM从excel文件中读取文件极度浪费时间。这就像用坦克杀死苍蝇一样。考虑到win32com使用windows API执行复杂的调用,与excel通信,检索数据并将其发送回python。当信息作为文件存在时,为什么这样做?
有些库可以直接解析excel文件,你可以想象它们的速度可以快100倍,因为对于win API没有过于复杂的调用。
我使用openpyxl成功地做了很多工作,但是还有其他库可以做得更好甚至更好。
只是大数据的一个例子(使用生成器而不是将所有内容加载到内存中):
from openpyxl import load_workbook
wb = load_workbook(filename='large_file.xlsx', use_iterators=True)
ws = wb.get_sheet_by_name(name='big_data') # ws is now an IterableWorksheet
for row in ws.iter_rows(): # it brings a new method: iter_rows()
for cell in row:
print cell.internal_value
可以使用等效方法写入单元格。你甚至可以格式化它们,虽然它不是(或曾经)非常完整。
修改强>
如何将大量信息写入xlsx
文件的示例:
from openpyxl import Workbook
from openpyxl.cell import get_column_letter
wb = Workbook()
dest_filename = r'empty_book.xlsx'
ws = wb.active
ws.title = "range names"
for col_idx in xrange(1, 40):
col = get_column_letter(col_idx)
for row in xrange(1, 600):
ws.cell('%s%s'%(col, row)).value = '%s%s' % (col, row)
ws = wb.create_sheet()
ws.title = 'Pi'
ws['F5'] = 3.14
wb.save(filename=dest_filename)