You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用gspread遍历Google Sheets所有工作表写入数据时循环提前退出问题

问题场景

我尝试使用Python的gspread库修改一份Google Sheets表格,表格内包含多个格式统一、对应不同房间的工作表,参考示意图:
多房间工作表结构示意图

现有实现代码如下:

room_list = sh.worksheets()
room = []
b = 0
for randioom in room_list:
    temp = str(room_list[b])
    print (temp)
    temp_room_list = re.findall(r"'([^'\\]*(?:\\.[^'\\]*)*)", temp)
    room.append(temp_room_list[0])
b+=1
print (room)
c = 0
d = 1
wks1 = sh.worksheet("List of Applicants")
for randission in splitted_email:
    result = wks1.row_values(wks1.find(str(splitted_email[c][0])).row)
    c+=1
    wks2 = sh.worksheet(str(room[d]))
    x = 0
    y = ['B', 'C', 'D', 'E']
    row = 0
    try:
        col = str((len(wks2.col_values("2"))) + 1)
        for details in range (0, 4, +1):
            wks2.update(str(y[row] + col), result[x])
            x+=1
            row+=1
            b+=1
    except gspread.exceptions.APIError as full:
        print("Room is full, Going to another room")
        time.sleep(2)
        print("Scanning Rooms")
        
        d+=1
        wks2 = sh.worksheet(str(room[d]))
        col = str((len(wks2.col_values("2"))) + 1)
        for details in range (0, 4, +1):
            wks2.update(str(y[row] + col), result[x])
            x+=1
            row+=1
            b+=1
    continue
现有逻辑与问题

上述代码的设计逻辑为:先获取所有工作表名称列表,之后遍历拆分后的邮箱列表,先在List of Applicants工作表中匹配对应邮箱所在行的完整数据,尝试将数据写入目标房间工作表;当写入触发gspread.exceptions.APIError错误(代表当前房间工作表已满)时,将工作表索引d加1,切换到下一个工作表尝试写入。

当前代码存在异常:运行时仅会检查2个工作表(RM 202 8AM和RM 202 10AM),无法遍历全部工作表查找存在剩余写入空间的工作表写入数据,需要修改代码实现遍历所有工作表,遇到满表时自动切换到下一个有空位的工作表,避免循环提前退出。

问题原因
  • 工作表名称获取逻辑存在缩进bug:b+=1写在了for循环外部,配合正则解析工作表对象字符串的冗余逻辑,本身就无法正确拿到全量工作表名。实际上gspread的Worksheet对象自带.title属性可以直接获取表名,完全不需要正则解析。
  • 房间切换逻辑仅做单次跳转:except块里只执行了一次d+=1切换到下一个表,如果第二个表也满了,代码不会继续往后查找,直接抛出异常退出。
  • 写入逻辑重复冗余:try块和except块里各写了一遍写入逻辑,很容易出现变量未重置导致的写入错位、索引越界问题。
  • 全局索引d不会做边界校验:当d的值超过房间工作表总数时,会直接触发列表索引越界错误。
修复后代码
import gspread
import time
# 保留你原有的gspread鉴权、表格获取逻辑
# sh = 你的Spreadsheet对象

# 1. 直接获取所有房间工作表,过滤掉申请人总表,无需正则解析
all_ws = sh.worksheets()
room_ws_list = [ws for ws in all_ws if ws.title != "List of Applicants"]
applicant_ws = sh.worksheet("List of Applicants")
write_cols = ['B', 'C', 'D', 'E']

for email in splitted_email:
    # 提取申请人在总表的对应数据
    match_row = applicant_ws.find(str(email[0])).row
    applicant_info = applicant_ws.row_values(match_row)[:4]
    write_done = False

    # 2. 遍历所有房间表找空位,不是仅跳转一次
    for room_ws in room_ws_list:
        try:
            # 计算当前房间B列的下一个空行
            next_empty_row = str(len(room_ws.col_values(2)) + 1)
            # 逐列写入数据
            for idx, col in enumerate(write_cols):
                room_ws.update(f"{col}{next_empty_row}", applicant_info[idx])
                time.sleep(0.1) # 加短延迟避免触发Google API限流
            print(f"申请人 {email[0]} 已写入房间 {room_ws.title}")
            write_done = True
            break
        except gspread.exceptions.APIError:
            print(f"房间 {room_ws.title} 已满,尝试下一个房间")
            time.sleep(2)
            continue
    
    if not write_done:
        print(f"所有房间均已满,申请人 {email[0]} 写入失败")
优化说明
  • 去掉了冗余的正则解析逻辑,直接通过官方API提供的.title属性获取工作表名,从根源避免表名获取不全的问题。
  • 把单次房间跳转改为全量房间遍历,只要当前房间写入失败就自动尝试下一个,直到找到有空位的房间或遍历完所有房间。
  • 合并了重复的写入逻辑,避免变量未重置导致的写入错位问题。
  • 增加了全满场景的提示,不会出现无提示崩溃的情况。

如果不需要每次录入新申请人都从第一个房间开始扫描,可以维护一个全局的当前房间索引,每次写入成功后记录当前写到的房间位置,下次从该位置开始扫描,能减少不必要的API调用。

内容的提问来源于stack exchange,提问作者CSAPawn

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 11:33:15