使用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
相关产品推荐
相关产品推荐

