gspread update_cell 很慢
gspread update_cell very slow
我有两个 google 电子表格:
QC- 很多列,我想检查第 4 列的值是否出现在第二个电子表格中 lastEdited_PEID;如果是,它将把 'Bingo!' 放在找到值的同一行的第 14 列中
lastEdited- 一栏,值的长电子表格
我用下面的代码实现了:
#acces the documents on Drive
QC = gc.open_by_key("FIRST KEY").sheet1
lastEdited = gc.open_by_key("SECOND KEY").sheet1
#get values from columns and convert to lists
QC_PEID = QC.col_values(4)
lastEdited_PEID = lastEdited.col_values(1)
#iterate by rows and check if value from each row appears in the second document
for value in QC_PEID:
ind = QC_PEID.index(value)
if value in lastEdited_PEID:
QC.update_cell(ind, 14, 'Bingo!')
所以它完成了工作,但速度很慢(大约 5 分钟)。我担心速度,因为我必须对大约 50 个电子表格(每个平均 6000 行)执行操作。
我尝试在循环中使用以下代码从第二个列表中删除该元素(它只能出现一次):
for value in QC_PEID:
ind = QC_PEID.index(value)
if value in lastEdited_PEID:
QC.update_cell(ind, 14, 'Bingo!')
**lastEdited_PEID.remove('value')**
我认为它会更快,因为参考列表会更短,但令人惊讶的是它需要更多。
我可以做些什么来加快这个过程?
由于 gspread 是 Google Sheet 的 REST API 的包装器,您在电子表格上执行的每个操作都会呈现为对 API 的 HTTP 请求。大多数时候这是代码中最慢的部分。如果你想提高性能,你需要弄清楚如何减少与 API.
的交互次数
在您的代码示例中,每个 col_values()
调用都会发出一个 HTTP 请求。这很好。但是,当您遍历单元格值时,循环中有一个 update_cell()
:
for value in QC_PEID:
ind = QC_PEID.index(value)
if value in lastEdited_PEID:
QC.update_cell(ind, 14, 'Bingo!') # it makes 2 HTTP requests each time
update_cell
向 API 发出 两个 HTTP 请求(一个用于检索更新单元格所需的信息,另一个用于实际将更新发送到API.) 你需要避免在你的循环中调用这个方法。
一个更好的主意是收集所有更新并分批发送。这就是 update_cells()
方法的用途。
update_cells()
需要 Cell
个对象的列表来进行批量更新。您可以通过致电 Worksheet.range()
.
获取这些信息
这是我想到的:
# A utility method
def col_cells(worksheet, col):
"""Returns a range of cells in a `worksheet`'s column `col`."""
start_cell = self.get_addr_int(1, col)
end_cell = self.get_addr_int(worksheet.row_count, col)
return worksheet.range('%s:%s' % (start_cell, end_cell))
QC_PEID = QC.col_values(4)
lastEdited_PEID = set(lastEdited.col_cells(1)) # make the 'in' lookup a bit faster
column_14_cells = col_cells(QC, 14)
has_updates = False
# iterate by rows and check if value from each row appears in the second document
for i, value in enumerate(QC_PEID):
if value in lastEdited_PEID:
has_updates = True
column_14_cells[i].value = 'Bingo!'
if has_updates:
QC.update_cells(column_14_cells)
我没有 运行 密码。小心错别字。
我有两个 google 电子表格:
QC- 很多列,我想检查第 4 列的值是否出现在第二个电子表格中 lastEdited_PEID;如果是,它将把 'Bingo!' 放在找到值的同一行的第 14 列中
lastEdited- 一栏,值的长电子表格
我用下面的代码实现了:
#acces the documents on Drive
QC = gc.open_by_key("FIRST KEY").sheet1
lastEdited = gc.open_by_key("SECOND KEY").sheet1
#get values from columns and convert to lists
QC_PEID = QC.col_values(4)
lastEdited_PEID = lastEdited.col_values(1)
#iterate by rows and check if value from each row appears in the second document
for value in QC_PEID:
ind = QC_PEID.index(value)
if value in lastEdited_PEID:
QC.update_cell(ind, 14, 'Bingo!')
所以它完成了工作,但速度很慢(大约 5 分钟)。我担心速度,因为我必须对大约 50 个电子表格(每个平均 6000 行)执行操作。
我尝试在循环中使用以下代码从第二个列表中删除该元素(它只能出现一次):
for value in QC_PEID:
ind = QC_PEID.index(value)
if value in lastEdited_PEID:
QC.update_cell(ind, 14, 'Bingo!')
**lastEdited_PEID.remove('value')**
我认为它会更快,因为参考列表会更短,但令人惊讶的是它需要更多。
我可以做些什么来加快这个过程?
由于 gspread 是 Google Sheet 的 REST API 的包装器,您在电子表格上执行的每个操作都会呈现为对 API 的 HTTP 请求。大多数时候这是代码中最慢的部分。如果你想提高性能,你需要弄清楚如何减少与 API.
的交互次数在您的代码示例中,每个 col_values()
调用都会发出一个 HTTP 请求。这很好。但是,当您遍历单元格值时,循环中有一个 update_cell()
:
for value in QC_PEID:
ind = QC_PEID.index(value)
if value in lastEdited_PEID:
QC.update_cell(ind, 14, 'Bingo!') # it makes 2 HTTP requests each time
update_cell
向 API 发出 两个 HTTP 请求(一个用于检索更新单元格所需的信息,另一个用于实际将更新发送到API.) 你需要避免在你的循环中调用这个方法。
一个更好的主意是收集所有更新并分批发送。这就是 update_cells()
方法的用途。
update_cells()
需要 Cell
个对象的列表来进行批量更新。您可以通过致电 Worksheet.range()
.
这是我想到的:
# A utility method
def col_cells(worksheet, col):
"""Returns a range of cells in a `worksheet`'s column `col`."""
start_cell = self.get_addr_int(1, col)
end_cell = self.get_addr_int(worksheet.row_count, col)
return worksheet.range('%s:%s' % (start_cell, end_cell))
QC_PEID = QC.col_values(4)
lastEdited_PEID = set(lastEdited.col_cells(1)) # make the 'in' lookup a bit faster
column_14_cells = col_cells(QC, 14)
has_updates = False
# iterate by rows and check if value from each row appears in the second document
for i, value in enumerate(QC_PEID):
if value in lastEdited_PEID:
has_updates = True
column_14_cells[i].value = 'Bingo!'
if has_updates:
QC.update_cells(column_14_cells)
我没有 运行 密码。小心错别字。