如何解决Python中gspread上传大CSV文件的ReadTimeout超时问题
解决gspread上传大CSV时的ReadTimeout问题
嘿,我来帮你搞定这个超时的麻烦!从你遇到的ReadTimeout: HTTPSConnectionPool(host='sheets.googleapis.com', port=443): Read timed out. (read timeout=120)错误能看出来,gspread默认的120秒超时时间不足以支撑51MB文件的上传,咱们可以通过自定义请求会话来延长超时时间,甚至加上重试策略让上传更稳定,下面给你具体的操作方法:
方法一:自定义Session延长超时时间
gspread底层依赖requests库,我们可以创建一个自定义的requests.Session对象,设置更长的超时时间,再把这个会话传给gspread的授权方法,这样所有请求都会使用这个超时设置。
修改你的CSV_Import函数如下:
def CSV_Import(csv_file='', gsheet_file_id='', gsheet_tab_name = ''): import requests from requests.adapters import HTTPAdapter from urllib3.util.retry import Retry import csv from oauth2client.service_account import ServiceAccountCredentials import gspread scope = ["https://spreadsheets.google.com/feeds", 'https://www.googleapis.com/auth/spreadsheets', "https://www.googleapis.com/auth/drive.file", "https://www.googleapis.com/auth/drive"] credentials = ServiceAccountCredentials.from_json_keyfile_name('googlecredentials.json', scope) # 创建自定义会话,设置超时时间(这里设为300秒=5分钟,可根据文件大小调整) session = requests.Session() session.timeout = 300 # 你可以改成600秒(10分钟)甚至更长 # 可选:添加重试策略,应对临时网络波动 retry_strategy = Retry( total=3, # 重试3次 backoff_factor=1, # 每次重试间隔递增(1秒、2秒、4秒...) status_forcelist=[429, 500, 502, 503, 504] # 遇到这些状态码时重试 ) adapter = HTTPAdapter(max_retries=retry_strategy) session.mount("https://", adapter) session.mount("http://", adapter) # 用自定义会话授权gspread客户端 client = gspread.authorize(credentials, session=session) sh = client.open_by_key(gsheet_file_id) sh.values_update( gsheet_tab_name, params={'valueInputOption': 'USER_ENTERED'}, body={'values': list(csv.reader(open(csv_file)))}, )
方法二:分批次上传(更适合超大文件)
如果文件实在太大,即使延长超时还是容易出问题,建议把CSV分成小批次上传,每个批次只传几百行,这样单个请求的耗时会短很多,也更容易排查问题。
示例代码如下:
def CSV_Import(csv_file='', gsheet_file_id='', gsheet_tab_name = '', batch_size=1000): import requests from requests.adapters import HTTPAdapter from urllib3.util.retry import Retry import csv from oauth2client.service_account import ServiceAccountCredentials import gspread scope = ["https://spreadsheets.google.com/feeds", 'https://www.googleapis.com/auth/spreadsheets', "https://www.googleapis.com/auth/drive.file", "https://www.googleapis.com/auth/drive"] credentials = ServiceAccountCredentials.from_json_keyfile_name('googlecredentials.json', scope) session = requests.Session() session.timeout = 300 retry_strategy = Retry( total=3, backoff_factor=1, status_forcelist=[429, 500, 502, 503, 504] ) adapter = HTTPAdapter(max_retries=retry_strategy) session.mount("https://", adapter) session.mount("http://", adapter) client = gspread.authorize(credentials, session=session) sh = client.open_by_key(gsheet_file_id) worksheet = sh.worksheet(gsheet_tab_name) # 分批读取并上传CSV内容 with open(csv_file, 'r') as f: reader = csv.reader(f) # 先上传表头 header = next(reader) worksheet.update('A1', [header]) batch = [] current_row = 2 # 从第二行开始上传数据 for row in reader: batch.append(row) # 达到批次大小就上传 if len(batch) >= batch_size: # 计算当前批次的单元格范围 end_col = chr(ord('A') + len(row) - 1) end_row = current_row + len(batch) - 1 range_str = f'A{current_row}:{end_col}{end_row}' worksheet.update(range_str, batch, value_input_option='USER_ENTERED') current_row = end_row + 1 batch = [] # 上传剩余的最后一批数据 if batch: end_col = chr(ord('A') + len(row) - 1) end_row = current_row + len(batch) - 1 range_str = f'A{current_row}:{end_col}{end_row}' worksheet.update(range_str, batch, value_input_option='USER_ENTERED')
小提示
- 超时时间不用设置得过于夸张,根据你的文件大小和网络环境调整即可,比如51MB的文件,300秒基本足够。
- 重试策略是可选的,但加上后能有效应对临时的网络卡顿或服务器限流,提升上传成功率。
内容的提问来源于stack exchange,提问作者Philip
相关产品推荐
相关产品推荐

