如何使用Azure Function将xlsb转xlsx?部署故障求助
问题描述
我开发了一个将xlsb文件转换为xlsx的函数,本地测试成功,但部署到Azure Portal运行时出现报错:
Result: Failure Exception: OSError: [Errno 30] Read-only file system: 'TEST.xlsx'
查资料后得知,基于Linux的Python版Azure Function只能把文件保存到临时目录,于是修改了函数,结果又出现新错误:
Result: Failure Exception: FileNotFoundError: [Errno 2] No such file or directory: '/tmp/TEST.xlsb'
现在需要实现基于Blob触发的Azure Function,把Blob容器里的xlsb文件转换成xlsx后保存回原容器。以下是我的两次尝试代码:
初次尝试代码
import os import logging import pandas as pd #from io import BytesIO import azure.functions as func from azure.storage.blob import BlobServiceClient, ContainerClient, BlobClient app = func.FunctionApp() @app.blob_trigger(arg_name="myblob", path="{containerName}/{name}.xlsb", connection="BlobStorageConnectionString") def blob_trigger(myblob: func.InputStream): logging.info(f"Python blob trigger function processed blob" f"Name: {myblob.name}" f"Blob Size: {myblob.length} bytes") accountName = "name" accountKey = "key" connectionString = f"DefaultEndpointsProtocol=https;AccountName={accountName};AccountKey={accountKey};EndpointSuffix=core.windows.net" containerName = "{containerName}" inputBlobname = myblob.name.replace({containerName}, "") outputBlobname = inputBlobname.replace(".xlsb", ".xlsx") blob_service_client = BlobServiceClient.from_connection_string(connectionString) container_client = blob_service_client.get_container_client(containerName) blob_client = container_client.get_blob_client(inputBlobname) blob = BlobClient.from_connection_string(conn_str=connectionString, container_name=containerName, blob_name=outputBlobname) df = pd.read_excel(blob_client.download_blob().readall(), engine="pyxlsb") df.to_excel(outputBlobname, index=False) with open(outputBlobname, "rb") as data: blob.upload_blob(data, overwrite=True)
修改后代码
import os import logging import pandas as pd #from io import BytesIO import azure.functions as func from azure.storage.blob import BlobServiceClient, ContainerClient, BlobClient app = func.FunctionApp() @app.blob_trigger(arg_name="myblob", path="{containerName}/{name}.xlsb", connection="BlobStorageConnectionString") def blob_trigger(myblob: func.InputStream): logging.info(f"Python blob trigger function processed blob" f"Name: {myblob.name}" f"Blob Size: {myblob.length} bytes") accountName = "name" accountKey = "key" connectionString = f"DefaultEndpointsProtocol=https;AccountName={accountName};AccountKey={accountKey};EndpointSuffix=core.windows.net" containerName = "{containerName}" inputBlobname = myblob.name.replace({containerName}, "") localBlobname = "/tmp/" + inputBlobname outputBlobname = inputBlobname.replace(".xlsb", ".xlsx") blob_service_client = BlobServiceClient.from_connection_string(connectionString) container_client = blob_service_client.get_container_client(containerName) blob_client = container_client.get_blob_client(inputBlobname) blob = BlobClient.from_connection_string(conn_str=connectionString, container_name=containerName, blob_name=outputBlobname) df = pd.read_excel(blob_client.download_blob().readall(), engine="pyxlsb") df.to_excel("/tmp/" + outputBlobname, index=False) ROOT_DIR = os.path.abspath(os.path.join(os.path.dirname(__file__), "..")) with open(file = os.path.join(ROOT_DIR, localBlobname), mode="rb") as data: blob.upload_blob(data, overwrite=True)
错误分析
- 第一个错误:Linux环境的Azure Function默认文件系统只读,不能直接在当前目录创建文件,必须使用
/tmp临时目录。 - 第二个错误:修改后的代码逻辑混乱——既没把源xlsb文件下载到
/tmp,却尝试读取该路径的文件;硬编码{containerName}无法正确获取触发器传入的容器名,导致inputBlobname路径处理错误;最后要上传的应该是生成的xlsx文件,不是源xlsb文件。
解决方案
直接用内存流处理文件转换,避免写入临时文件,同时修正容器名和文件名的获取逻辑,用环境变量存储连接字符串:
import io import os import logging import pandas as pd import azure.functions as func from azure.storage.blob import BlobClient app = func.FunctionApp() @app.blob_trigger(arg_name="myblob", path="{containerName}/{name}.xlsb", connection="BlobStorageConnectionString") def blob_trigger(myblob: func.InputStream, containerName: str): logging.info(f"处理Blob: 名称={myblob.name}, 大小={myblob.length}字节") # 提取Blob文件名并替换后缀为xlsx blob_name = myblob.name.split("/")[-1] output_blob_name = blob_name.replace(".xlsb", ".xlsx") # 初始化输出Blob客户端,用环境变量读取连接字符串 blob_client = BlobClient.from_connection_string( conn_str=os.getenv("BlobStorageConnectionString"), container_name=containerName, blob_name=output_blob_name ) # 直接从触发器输入流读取并解析xlsb文件 df = pd.read_excel(myblob.read(), engine="pyxlsb") # 将DataFrame写入内存流,无需临时文件 output_stream = io.BytesIO() df.to_excel(output_stream, index=False) output_stream.seek(0) # 重置流指针到起始位置 # 上传转换后的xlsx文件到Blob容器 blob_client.upload_blob(output_stream, overwrite=True) logging.info(f"转换完成,已上传文件: {output_blob_name}")
注意事项
- 在Azure Function应用的配置-环境变量中添加
BlobStorageConnectionString,不要硬编码账户名和密钥,避免泄露。 - 确保
requirements.txt中包含依赖包:pandas>=2.0.0 pyxlsb>=1.0.10 azure-functions>=1.17.0 azure-storage-blob>=12.19.0 - Linux环境的
/tmp目录有大小限制(默认5GB),超大文件建议分片处理或继续优化内存使用。
内容的提问来源于stack exchange,提问作者SQL_Noob
相关产品推荐
相关产品推荐

