GSPREAD 在单独的工作表上批量导出数据帧,而不触发 API 写入请求限制

问题描述 投票:0回答:2

将一些相对较小的数据帧写入单个电子表格时,我遇到了 gsheet api 的写入请求配额。

数据帧保存在字典中。 KEY 用于 SHEET 名称,VALUE 是要导出的数据帧。

现在我正在循环中运行数据帧,创建工作表并保存数据。

gc = gspread.oauth(credentials_filename=credential_path("credentials.json"),
                   authorized_user_filename=credential_path("token.json")
                   )

gc_sh = gc.create('rote_output_' + yyyymmddhhss())


# (rote_data is the dictionary of dataframes)
for k, v in rote_data.items():
    gc_sh.add_worksheet(title=k, rows=100, cols=20)
    worksheet = gc_sh.worksheet(k)
    worksheet.update([v.columns.values.tolist()] + (v.fillna('')).values.tolist())
    worksheet.freeze(rows=1)

感觉循环中的四个“操作”被视为单独的调用,因此,如果我有 15 个数据帧,我会立即发出 60 个写入请求,从而触发 api 块。

有没有办法将更新作为“批量”请求进行,以免达到这些限制? batch_update() 文档的细节很少,我不确定是否可以使用此公式创建然后保存到不同的工作表,这将是理想的。

** 编辑: 如何通过gspread和python在电子表格中创建多个工作表?

从这个问题/答案看来,batch_update可能能够做到这一点,尽管尚不清楚我如何将创建工作表的请求与每张工作表上数据的实际更新结合起来

client =  # Please use your client.

employee_names = ["Jonny", "Emma",,,] # Please set the sheet names. spreadsheetId = "###" # Please set your spreadsheet ID.

requests = [
    {
        "addSheet": {
            "properties": {
                "title": e,
                "gridProperties": {"rowCount": 100, "columnCount": 20},
            }
        }
    }
    for e in employee_names ]  
spreadsheet = client.open_by_key(spreadsheetId)
spreadsheet.batch_update({"requests": requests})
python pandas google-sheets google-sheets-api gspread
2个回答
0
投票

首先,我们在一个

batch_update
请求中整理所有表格。

import gspread
from google.oauth2.service_account import Credentials

# Initialize the gspread client
credentials = Credentials.from_service_account_file(credential_path("credentials.json"))
gc = gspread.authorize(credentials)

# Create a new spreadsheet
gc_sh = gc.create('rote_output_' + yyyymmddhhss())

# Prepare the batch request to create sheets
requests = [
    {
        "addSheet": {
            "properties": {
                "title": sheet_name,
                "gridProperties": {"rowCount": 100, "columnCount": 20},
            }
        }
    }
    for sheet_name in rote_data.keys()
]

# Execute the batch request to create all sheets
gc_sh.batch_update({"requests": requests})

制作好表格后,我们将做好一切准备,以便对每张表格进行另一轮更新。

import numpy as np

# Prepare the batch update request for data
requests = []
for sheet_name, df in rote_data.items():
    worksheet = gc_sh.worksheet(sheet_name)
    values = [df.columns.values.tolist()] + df.fillna('').values.tolist()
    data_range = f'A1:{chr(64 + df.shape[1])}{df.shape[0] + 1}'  # Adjust the range based on the dataframe size
    requests.append({
        "updateCells": {
            "range": {
                "sheetId": worksheet.id,
                "startRowIndex": 0,
                "startColumnIndex": 0,
                "endRowIndex": df.shape[0] + 1,
                "endColumnIndex": df.shape[1]
            },
            "rows": [
                {"values": [{"userEnteredValue": {"stringValue": str(cell)}} for cell in row]}
                for row in values
            ],
            "fields": "userEnteredValue"
        }
    })

# Execute the batch update request to add data to all sheets
gc_sh.batch_update({"requests": requests})

我们使用

batch_update
请求一次性创建所有工作表。每个工作表都用
addSheet
属性指定。

  • 准备要插入到每个数据框相应工作表中的数据
  • 计算数据范围(例如 A1:C10)以覆盖整个数据帧
  • 在batch_update中使用updateCells在单个请求中更新工作表的内容

0
投票

我相信您的目标如下。

  • 您想要创建一个新的 Google 电子表格。
  • 您想要在新电子表格中创建 60 个工作表。每张纸有 100 行和 20 列,您想要冻结每张纸中的第一行。
  • 您想要将值
    rote_data
    放入每张纸中。
  • 您想降低流程成本。

既然如此,下面的修改如何?

修改后的脚本:

gc_sh = gc.create('rote_output_' + yyyymmddhhss())

# --- I modified the below script.
# Create request bodies.
request1 = []
request2 = []
for k, v in rote_data.items():
    request1.append({"addSheet": {"properties": {"title": k, "gridProperties": {"rowCount": 100, "columnCount": 20, "frozenRowCount": 1}}}})
    request2.append({"range": f"'{k}'!A1", "values": [v.columns.values.tolist()] + (v.fillna('')).values.tolist()})

# Use Sheets API.
gc_sh.batch_update({"requests": request1})
gc_sh.values_batch_update({"data": request2, "valueInputOption": "USER_ENTERED"})
  • 在此修改中,2 个工作表 API 与
    request1
    request2
    一起使用。根据第一次请求,插入新的工作表。并且,在第二次请求时,这些值将被放入每个工作表中。

注:

  • 对于 Sheets API,当使用 方法:spreadsheets.create时,可以通过一次 API 调用合并
    gc_sh = gc.create('rote_output_' + yyyymmddhhss())
    gc_sh.batch_update({"requests": request1})
    。但是,在现阶段,gspread似乎没有使用“方法:spreadsheets.create”的方法。所以,我提出了上述修改。
  • 我无法知道你的
    rote_data
    的实际值。所以,为了使用
    "valueInputOption": "USER_ENTERED"
    ,我使用了
    values_batch_update

参考资料:

© www.soinside.com 2019 - 2024. All rights reserved.