2016-07-12 13 views
2

をupdate_cell:gspreadは、私は2枚のGoogleスプレッドシート持っている非常に遅い

QC-多くの列を、私は場合は、2番目のスプレッドシートlastEdited_PEIDの列4が表示されますから値を確認したいです。それがあれば、「ビンゴ!値は、値の

lastEdited-つの列、長いスプレッドシートを発見したのと同じ行の列14に

私は達成その次のコードで:

#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行)の操作を実行しなければならないので、速度が心配です。

Iは、ループ内の次のコードで(それは一度だけ現れることができる)が見つかりましたときに、第2のリストから要素を削除しようとした:

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')** 

私はそれがより速く参照リストと同じようにするだろうと思っ短くても驚くほど多くの時間がかかります。

処理を迅速に行うにはどうすればよいですか?

答えて

3

gspreadはGoogleシートのREST APIのラッパーです。スプレッドシートで実行する各操作は、APIへのHTTP要求にレンダリングされます。ほとんどの場合、これはコードの中で最も遅い部分です。パフォーマンスを向上させたい場合は、APIとのやりとり回数を減らす方法を理解する必要があります。

コードサンプルでは、​​それぞれcol_values()呼び出しによって1つの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は1つが、実際に送信するために、セルと別のものを更新するために必要な情報を取得するために、(APIへ2つの 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) 

私は、コードを実行されませんでした。タイプミスに注意してください。

+1

私のテストワークシートでは、処理時間が5分から2秒に短縮されました。バッチ更新によって違いが生じます。感謝万円! – pawelty

関連する問題