Python gspread 処理が遅いと感じたらチェックすること

こんにちは、kisseです。
最近、PythonでDBを叩いてその内容をスプレッドシートに書き出し、グラフの描画などを行っています。
この辺をスクリプトを早朝でcronで実行させとくと、朝の出社してすぐに前日までのデータを確認することができるようになります。

その中で、gspreadというライブラリを使用しているのですが、処理になかなか時間がかかっているのが気になって色々調査したのでその共有をします。

なぜ処理遅延が発生するのか?

gspreadというライブラリはGoogle Spread SheetをPythonから更新するためのものです。
これはGoogle Spread Sheet を更新するためのライブラリをラップしたものなので、特定のメソッドの内部処理にはAPIコールが含まれています。
一般にAPIコールはネットワークの向こうのリソースを扱うために、ネットワークの遅延が発生するほか、複数回のAPIコールには頻度の制限がかけられることがあります。

以上の理由から 多数のAPIコールは処理速度を低下させる ので、以下にAPIコールを少なくさせるようにメソッドを呼ぶのかが重要になります。



確認することリスト

  • セル1個ずつ取得してない?
  • セルの更新1つずつしていない?

以上の2つに注意して、コードを確認する必要があります。

セルを1個ずつ取得してない?

workspace.cell()workspace.acell()などを使うと、1つのセルを取得するために1回のAPIコールが必要になります。
APIコールの回数が多くなると、ネットワーク接続による遅延や、APIコールの頻度制限などに引っかかることによって、処理に時間がかかることが予想されます。

for文などで多数のセルを参照する場合には、1回のAPIコールで複数のセルを取得することができるworkspace.range()を使いましょう。
これにより、セル取得時の処理遅延を減らすことができます。

セルの更新を1つずつしていない?

workspace.update_cell()を使うと特定のセルの値を書き換えることができます。
しかし、このメソッドは1回のAPIコールで1つのセルの更新しかできないため、for文中などで多数のセルを更新するのには向きません。

workspace.update_cells()を用いると、複数のセルの内容を1度のAPIコールで更新することができます。

つまりどのようにするのが良いのか

処理速度の低下には、workspace.range()で複数のセルを取得して、値を書き換えてから、workspace.update_cells()でセルの一括更新を行いましょう。
うまく処理を構成することにより、最低2回のAPIコールで目的の更新を行うことができます。

サンプル

以下にサンプルを示します。
dataframeにDBへのクエリ結果が入ってるという想定で行います。
また、スプレッドシートへの接続、ワークスペースの接続は済んでいるものとします。

# dataframe: スプレッドシートに転記したいクエリ結果
# workspace: ワークスペース

# まずは列名を記入しよう

# 列名を記入するセルをリストとして取得(APIコール発生)
cell_list = workspace.range(1, 1, 1, len(dataframe.columns))

# セルの値を更新(まだ反映はしない)
for cell, val in zip(cell_list, dataframe.columns):
  cell.value = val

# セルの更新を反映(APIコール発生)
workspace.update_cells(cell_list)

# ここから、dataframeの内容を全て反映させる
for index, record in dataframe.iterrows():
  # 更新対象列を取得(APIコールを発生)
  cell_list = workspace.range(index + 2, 1, index + 2, len(record))

  # セルの更新を行う
  for cell, val in zip(cell_list, record):
    cell.value = val

  # セルの更新を反映(APIコール発生)
  workspace.update_cells(cell_list)

上記の例ではクエリ結果がN件だと2(N + 1)回のAPIコールが発生します。
workspace.update_cell()などを使うパターンなど比べて、APIコールが少なくなるので処理速度の向上が見込めます。



おわり

今回はgspreadでの処理が遅い原因と、処理速度向上のためのサンプルを示しました。

最後まで読んでいただきありがとうございます!

あわせて読みたい