在AWS Lambda中读取S3上的.mdb/.accdb文件并转CSV/Excel
在AWS Lambda中处理S3上的MS Access文件(.mdb/.accdb)
为什么pyodbc方案不可行
pyodbc依赖Microsoft Access ODBC驱动,而该驱动仅支持Windows环境。Lambda默认使用Amazon Linux运行时,无法安装该驱动,因此直接用pyodbc读取Access文件的方案在Lambda中根本无法运行。另外,S3是对象存储,不能直接通过文件路径访问,必须先将文件下载到Lambda的临时存储目录(/tmp/)。
可行解决方案:使用mdbtools + Lambda自定义层
mdbtools是一套Linux下的开源工具,支持读取.mdb和.accdb文件,我们可以通过自定义层将其部署到Lambda,再配合命令行工具导出表格为CSV,最后上传回S3。
步骤1:创建包含mdbtools的Lambda自定义层
Lambda默认环境没有mdbtools,需要自行编译并打包成层:
- 启动一台Amazon Linux 2的EC2实例(或用本地Linux环境模拟)
- 安装编译依赖:
sudo yum install -y gcc make automake libtool bzip2-devel git - 编译安装mdbtools:
git clone https://github.com/mdbtools/mdbtools.git cd mdbtools ./autogen.sh && ./configure && make && make install - 打包层文件:
mkdir -p mdbtools-layer/bin mdbtools-layer/lib cp /usr/local/bin/mdb* mdbtools-layer/bin/ cp /usr/local/lib/libmdb* mdbtools-layer/lib/ cd mdbtools-layer zip -r mdbtools-layer.zip . - 将
mdbtools-layer.zip上传到Lambda层,并关联到你的Lambda函数。
步骤2:Lambda函数代码实现
以下代码实现从S3下载Access文件,导出所有表格为CSV,再上传回S3的逻辑:
import boto3 import subprocess import os from botocore.exceptions import ClientError s3 = boto3.client('s3') def lambda_handler(event, context): # 从S3触发事件中提取桶名和文件路径 bucket = event['Records'][0]['s3']['bucket']['name'] key = event['Records'][0]['s3']['object']['key'] # 定义本地临时文件路径 filename = os.path.basename(key) local_access_path = f"/tmp/{filename}" # 下载S3文件到Lambda临时目录 try: s3.download_file(bucket, key, local_access_path) except ClientError as e: print(f"下载失败: {e}") return {"statusCode": 500, "body": "文件下载失败"} # 获取Access文件中的所有表格名 try: tables_output = subprocess.check_output( ["mdb-tables", "-1", local_access_path], stderr=subprocess.STDOUT, text=True ) tables = [t.strip() for t in tables_output.split('\n') if t.strip()] except subprocess.CalledProcessError as e: print(f"获取表格列表失败: {e.output}") return {"statusCode": 500, "body": "读取表格列表失败"} # 遍历表格导出为CSV并上传到S3 for table in tables: csv_filename = f"{os.path.splitext(filename)[0]}_{table}.csv" local_csv_path = f"/tmp/{csv_filename}" s3_csv_key = f"converted_output/{csv_filename}" # 导出表格为CSV try: with open(local_csv_path, 'w') as csv_file: subprocess.run( ["mdb-export", local_access_path, table], stdout=csv_file, stderr=subprocess.STDOUT, check=True ) except subprocess.CalledProcessError as e: print(f"导出表格{table}失败: {e.output}") continue # 上传CSV到S3 try: s3.upload_file(local_csv_path, bucket, s3_csv_key) print(f"成功上传: {s3_csv_key}") except ClientError as e: print(f"上传{csv_filename}失败: {e}") continue # 清理临时文件(可选,Lambda会自动回收临时存储) os.remove(local_access_path) for table in tables: csv_path = f"/tmp/{os.path.splitext(filename)[0]}_{table}.csv" if os.path.exists(csv_path): os.remove(csv_path) return {"statusCode": 200, "body": "所有表格转换完成"}
额外说明
- 转换为Excel:如果需要导出为Excel,可以在生成CSV后,用pandas将CSV转为Excel格式。需要额外创建包含pandas、openpyxl的Lambda层。
- 权限配置:确保Lambda执行角色拥有S3的
GetObject(读取源文件)和PutObject(上传转换后文件)权限。 - 文件大小限制:Lambda临时存储默认最大512MB,若Access文件超过此大小,需考虑使用EFS扩展存储。
- .accdb兼容性:mdbtools对.accdb的支持不如.mdb完善,若遇到兼容性问题,可以考虑使用Lambda Windows容器(支持安装Access ODBC驱动),但配置复杂度更高。
内容的提问来源于stack exchange,提问作者Tarundeep Singh
相关产品推荐
相关产品推荐

