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

使用Cloud Functions写入GCS遇OSError: [Errno 30]只读文件系统错误

Cloud Functions触发写入GCS报错:Read-only file system

问题场景

用Python编写Cloud Functions实现Dataframe转xlsx并写入GCS,测试和部署阶段正常,但通过Pub/Sub+Scheduler触发时抛出OSError: [Errno 30] Read-only file system错误。

初始代码:

bucket_name = 'bucket-main'
blob_name = 'file-reception/'

df = client.query(query).to_dataframe()
xlsx_file = 'test'
writer = pandas.ExcelWriter(xlsx_file)
df.to_excel(writer, index=False)

bucket = storage_client.get_bucket(bucket_name)
blob = bucket.blob(blob_name+xlsx_file)
blob.upload_from_filename(xlsx_file)

尝试更换df.to_excel的引擎(xlsxwriter、openpyxl)后问题仍存在,自行修改的代码还存在参数错误(如upload_from_filename传入writer对象)。

原因分析

Cloud Functions的运行环境中,仅/tmp目录具备读写权限,测试阶段本地开发环境的当前工作目录可写,所以直接写入当前目录没问题;但通过Pub/Sub触发的生产环境中,当前工作目录是只读状态,因此写入非/tmp路径时触发权限错误。

正确解决方案

方案1:使用临时目录/tmp写入文件

修改代码,将Excel文件写入/tmp目录,同时修正参数错误,并确保关闭writer:

import pandas as pd
from google.cloud import storage

bucket_name = 'bucket-main'
blob_name = 'file-reception/'

# 从查询获取Dataframe
df = client.query(query).to_dataframe()
xlsx_filename = 'test.xlsx'  # 添加.xlsx后缀便于格式识别
tmp_file_path = f'/tmp/{xlsx_filename}'

# 创建ExcelWriter并写入数据
writer = pd.ExcelWriter(tmp_file_path, engine='xlsxwriter')
df.to_excel(writer, index=False)
writer.close()  # 必须关闭writer,确保文件完全写入磁盘

# 上传至GCS
storage_client = storage.Client()
bucket = storage_client.get_bucket(bucket_name)
blob = bucket.blob(f'{blob_name}{xlsx_filename}')
blob.upload_from_filename(tmp_file_path)

方案2:内存流方式(更高效,无需本地文件)

直接在内存中生成Excel文件,避免写入临时目录,适合无服务器场景:

import pandas as pd
from google.cloud import storage
from io import BytesIO

bucket_name = 'bucket-main'
blob_name = 'file-reception/'

df = client.query(query).to_dataframe()
xlsx_filename = 'test.xlsx'

# 用BytesIO在内存中生成Excel
output = BytesIO()
writer = pd.ExcelWriter(output, engine='xlsxwriter')
df.to_excel(writer, index=False)
writer.close()
output.seek(0)  # 重置流指针到起始位置

# 上传到GCS
storage_client = storage.Client()
bucket = storage_client.get_bucket(bucket_name)
blob = bucket.blob(f'{blob_name}{xlsx_filename}')
# 指定Content-Type,确保GCS识别为Excel文件
blob.upload_from_file(output, content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet')

关键注意事项

  • 仅/tmp目录可写:Cloud Functions生产环境中,只有/tmp具备读写权限,其他目录均为只读。
  • 关闭ExcelWriter:必须调用writer.close()或使用with上下文管理器,否则文件可能未完全写入,导致上传损坏或空文件。
  • 参数正确性:upload_from_filename需要传入文件路径字符串,而非writer对象;upload_from_file则需传入打开的文件流。
  • 文件格式标识:建议添加.xlsx后缀,并在上传时指定Content-Type,避免后续使用时出现格式识别问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 00:57:04