Python 在OpenPYXL中运行50k行Excel文件的最快方法
我在python中使用openpyxl,我尝试运行50k行,从每行获取数据并将其放入文件中。然而。。我发现它跑得越远,速度就越慢。第一条1k线路的速度非常快,不到一分钟,但在那之后,接下来的1k线路的运行时间越来越长 我正在打开一个.xlsx文件。我想知道以csv或其他方式打开.txt文件或读取json文件或其他方式是否更快?或者以某种方式转换成阅读速度更快的东西 在给定的列中有20个唯一的值,然后每个值都是随机的。我试图为每个值获取整个唯一值列的字符串 价值1:1243345,34124, 价值2:1243345,34124, 等等等等 我正在运行值列表,查看文件中是否存在该名称,如果存在,则它将访问该文件并向其附加新值,如果该文件不存在,则它将创建该文件,然后将其设置为“附加”。我有一个字典,它连接了所有的“附加写文件”的东西,所以每当我想写东西的时候,它都会抓取文件名,附加的东西会出现在dict中,它会查找并写入该文件,所以它不会每次运行都打开新文件 第一个1k不到一分钟。。现在我有4k到5k的记录,5分钟后就可以运行了。。它似乎需要更长的时间,因为它在记录中上升,我想知道如何加快它。它根本没有打印到控制台Python 在OpenPYXL中运行50k行Excel文件的最快方法,python,excel,performance,openpyxl,Python,Excel,Performance,Openpyxl,我在python中使用openpyxl,我尝试运行50k行,从每行获取数据并将其放入文件中。然而。。我发现它跑得越远,速度就越慢。第一条1k线路的速度非常快,不到一分钟,但在那之后,接下来的1k线路的运行时间越来越长 我正在打开一个.xlsx文件。我想知道以csv或其他方式打开.txt文件或读取json文件或其他方式是否更快?或者以某种方式转换成阅读速度更快的东西 在给定的列中有20个唯一的值,然后每个值都是随机的。我试图为每个值获取整个唯一值列的字符串 价值1:1243345,34124, 价
writeFile = 1
theDict = {}
for row in ws.iter_rows(rowRange):
for cell in row:
#grabbing the value
theStringValueLocation = "B" + str(counter)
theValue = ws[theStringValueLocation].value
theName = cell.value
textfilename = theName + ".txt"
if os.path.isfile(textfilename):
listToAddTo = theDict[theName]
listToAddTo.write("," + theValue)
if counter == 1000:
print "1000"
st = datetime.datetime.fromtimestamp(ts).strftime('%Y-%m-%d %H:%M:%S')
else:
writeFileName = open(textfilename, 'w')
writeFileName.write(theValue)
writeFileName = open(textfilename, 'a')
theDict[theName] = writeFileName
counter = counter + 1
我在上面的代码中添加了一些时间戳,它不在那里,但是您可以看到下面的输出。我看到的问题是,每跑1公里,它就会越来越高。第一时间是2分钟,第三分钟,第五分钟,第七分钟。当它达到50k的时候,我担心它会花上一个小时左右,而且会花太长时间
1000
2016-02-25 15:15:08
20002016-02-25 15:17:07
30002016-02-25 15:20:52
2016-02-25 15:25:28
4000
2016-02-25 15:32:00
5000
2016-02-25 15:40:02
6000
2016-02-25 15:51:34
7000
2016-02-25 16:03:29
8000
2016-02-25 16:18:52
9000
2016-02-25 16:35:30
10000
有些事我应该说清楚。。我事先不知道这些值的名称,也许我应该在一个单独的python脚本中运行并获取这些值,以加快速度
第二,我需要一个由逗号分隔的所有值组成的字符串,这就是为什么我把它放在一个文本文件中以便稍后获取。我正考虑按照建议的清单来做,但我不知道这是否会有同样的问题。我认为这个问题与读取excel有关。无论如何,我可以从中得到一个用逗号分隔的字符串,我可以用另一种方法
或者我可以做try/catch而不是每次都搜索文件,如果有错误,我可以假设创建一个新文件?也许每次查找都会让它运行得很慢?该文件是否存在
这个问题是我原来的问题的延续,我从那里得到了一些建议 看起来您只需要B列中的单元格。在这种情况下,您可以使用
ws.get_squared_range()
来限制要查看的单元格数量
for row in ws.get_squared_range(min_col=2, max_col=2, min_row=1, max_row=ws.max_row):
for cell in row: # each row is always a sequence
filename = cell.value
if os.path.isfilename(filename):
…
现在还不清楚代码的
else
分支发生了什么,但您可能应该在完成打开的所有文件后立即关闭它们。我认为您试图做的是从行的B列中获取一个键,并使用该键作为要附加到的文件名。让我们加快速度:
from collections import defaultdict
Value_entries = defaultdict(list) # dict of lists of row data
for row in ws.iter_rows(rowRange):
key = row[1].value
Value_entries[key].extend([cell.value for cell in row])
# All done. Now write files:
for key in Value_entries.keys():
with open(key + '.txt', 'w') as f:
f.write(','.join(Value_entries[key]))
根据您链接到的另一个问题和上面的代码,您似乎有一个名称-值对的电子表格。名称在列A中,值在列B中。名称可以在列A中出现多次,并且每次在列B中都可以有不同的值。目标是创建为每个名称显示的所有值的列表 首先,对上述代码的一些观察:
计数器
从未初始化。大概它被初始化为1open(textfilename,…)
被调用两次,其间不关闭文件。调用open会分配一些内存来保存与文件操作相关的数据。分配给第一次打开调用的内存可能要到很久以后才能释放,可能要到程序结束时才会释放。更好的做法是在处理完文件后关闭它们(请参阅使用open作为上下文管理器)for cell in row: # cell refers to A1
valueLocation = "B" + str(counter) # valueLocation is "B1"
value = ws[valueLocation].value # value gets contents of cell B1
name = cell.value # name gets contents of cell A1
textfilename = name + ".txt"
...
opens file with name based on contents of cell A1, and
writes value from cell B1 to the file
...
counter = counter + 1 # counter = 2
for cell in row: # cell now refers to cell B1
valueLocation = "B" + str(counter) # valueLocation is "B2"
value = ws[valueLocation].value # value gets contents of cell B2
name = cell.value # name gets contents of cell B1
textfilename = name + ".txt"
...
opens file with name based on contents of cell "B1" <<<< wrong file
writes the value of cell "B2" to the file <<<< wrong value
...
counter = counter + 1 # counter = 3 when cell B1 is processed
但每行至少有两个单元格,因此在内部循环的第二次迭代中:
for cell in row: # cell refers to A1
valueLocation = "B" + str(counter) # valueLocation is "B1"
value = ws[valueLocation].value # value gets contents of cell B1
name = cell.value # name gets contents of cell A1
textfilename = name + ".txt"
...
opens file with name based on contents of cell A1, and
writes value from cell B1 to the file
...
counter = counter + 1 # counter = 2
for cell in row: # cell now refers to cell B1
valueLocation = "B" + str(counter) # valueLocation is "B2"
value = ws[valueLocation].value # value gets contents of cell B2
name = cell.value # name gets contents of cell B1
textfilename = name + ".txt"
...
opens file with name based on contents of cell "B1" <<<< wrong file
writes the value of cell "B2" to the file <<<< wrong value
...
counter = counter + 1 # counter = 3 when cell B1 is processed
代码的缩进是错误的,这意味着我们无法判断循环的结构。为什么要迭代单元格,然后访问某行B列中的单元格?我猜
ws[“B”+str(计数器)]。value
以线性时间wrt运行<代码>计数器,不是在恒定时间内。否缩进没有错误。你明白了。。我有两个价值观。B一是“值”所在的位置。“cell.value”是名称。我在用柜台抓住彼此在同一排的那一个。哦,是的,你说得对。。第行的单元格后面应该有缩进。。我会修好的,我不知道你想做什么。提供输入电子表格的几行/几列以及一个或两个输出文件的外观可能会有所帮助。另外,您要打开多少个文件?性能应该是线性的。如果不是这样,那么你可能在某个地方有一个嵌套循环。else分支是如果文件不存在,它会创建文件,然后保持打开状态,这样我就可以在每个文件的末尾添加“,”,这样它就不必每次都重新打开文件,它只会保持打开状态,大约有20个文件将被打开,我建议您使用标准库中的profile模块来找出代码在哪里花费了大部分时间,而不是在这里提供一个带有时间戳的不完整脚本。。我不知道他们有,有没有一个超快速的方法来设置?看起来我看到的一切都很复杂你不需要计算A1