如何在AWS Glue Python任务中实现DOC转PDF?LibreOffice依赖遇阻
在AWS Glue中实现DOC转PDF的可行方案
我已经成功在AWS Glue中实现过DOC(含文本、图片、表格)转PDF的需求,核心是解决LibreOffice在Glue运行环境中的依赖部署问题,以下是具体的实现方案:
核心问题分析
Glue的默认运行环境(无论是Python Shell还是Spark作业)并未预装LibreOffice,且默认环境缺少LibreOffice运行所需的依赖库(如X11相关组件),这就是你在Python任务中调用命令失败的原因。
方案1:Glue Python Shell作业(轻量单文件/小批量处理)
适合处理单个或少量文件,步骤如下:
1. 准备LibreOffice依赖包
- 下载对应Amazon Linux 2的LibreOffice 7.6预编译二进制包(或rpm包集合),打包成ZIP文件。
- 将ZIP包上传到你的S3存储桶(例如
s3://your-bucket/deps/libreoffice7.6.zip)。
2. 配置Glue作业
- 在Glue作业的Python library path中添加上述S3 ZIP包的路径,Glue会自动将其解压到作业的临时运行环境。
- 确保作业执行角色拥有该S3路径的读取权限,以及输入/输出S3桶的读写权限。
3. Python代码实现
import os import subprocess import boto3 from zipfile import ZipFile # 初始化S3客户端 s3 = boto3.client('s3') # 1. 解压LibreOffice依赖 libre_zip = '/tmp/libreoffice7.6.zip' s3.download_file('your-bucket', 'deps/libreoffice7.6.zip', libre_zip) with ZipFile(libre_zip, 'r') as zf: zf.extractall('/tmp/libreoffice') # 2. 设置环境变量(关键:解决LibreOffice权限和路径问题) os.environ['HOME'] = '/tmp' # 让LibreOffice能写入临时文件 os.environ['PATH'] += ':/tmp/libreoffice/program' # 添加LibreOffice命令路径 # 3. 下载S3中的DOC文件到本地 input_doc = '/tmp/source.doc' s3.download_file('your-input-bucket', 'docs/source.doc', input_doc) # 4. 执行DOC转PDF命令 output_dir = '/tmp/pdf_output' os.makedirs(output_dir, exist_ok=True) subprocess.run( [ 'libreoffice7.6', '--headless', '--norestore', '--nofirststartwizard', '--convert-to', 'pdf', input_doc, '--outdir', output_dir ], check=True, capture_output=True ) # 5. 将生成的PDF上传回S3 output_pdf = os.path.join(output_dir, 'source.pdf') s3.upload_file(output_pdf, 'your-output-bucket', 'pdfs/source.pdf')
方案2:Glue Spark作业(大批量分布式处理)
适合批量处理大量DOC文件,利用Spark的分布式能力,步骤如下:
1. 使用Bootstrap脚本安装依赖
在Glue作业的Bootstrap action中添加以下脚本,让每个Executor启动时自动安装LibreOffice及依赖:
#!/bin/bash # 安装LibreOffice及所需依赖库 yum install -y libreoffice-headless libreoffice-writer libreoffice-calc libreoffice-impress libX11 libXext libXrender
注:如果需要特定版本(如7.6),可替换为手动下载对应rpm包并安装的命令。
2. Spark代码实现(Python版本)
from pyspark.sql import SparkSession import subprocess import os import boto3 def convert_doc_to_pdf(s3_path): # 解析S3路径 bucket, key = s3_path.replace('s3://', '').split('/', 1) s3 = boto3.client('s3') # 下载DOC到本地临时目录 local_doc = f'/tmp/{os.path.basename(key)}' s3.download_file(bucket, key, local_doc) # 执行转换 output_dir = '/tmp/pdf' os.makedirs(output_dir, exist_ok=True) subprocess.run( [ 'libreoffice7.6', '--headless', '--norestore', '--nofirststartwizard', '--convert-to', 'pdf', local_doc, '--outdir', output_dir ], check=True ) # 上传PDF回S3 pdf_name = os.path.splitext(os.path.basename(key))[0] + '.pdf' local_pdf = os.path.join(output_dir, pdf_name) s3.upload_file(local_pdf, bucket, f'pdf_output/{pdf_name}') # 清理临时文件 os.remove(local_doc) os.remove(local_pdf) if __name__ == '__main__': spark = SparkSession.builder.appName('DocToPdfConverter').getOrCreate() # 获取S3中的所有DOC文件路径 doc_paths = [f's3://your-input-bucket/docs/{f}' for f in os.listdir('s3://your-input-bucket/docs') if f.endswith('.doc')] # 分布式处理 spark.sparkContext.parallelize(doc_paths).foreach(convert_doc_to_pdf) spark.stop()
关键注意事项
- 必须设置
HOME=/tmp:LibreOffice无头模式需要写入临时文件,Glue默认的HOME目录无写入权限,指定/tmp可解决此问题。 - 添加
--norestore和--nofirststartwizard参数:避免LibreOffice启动时弹出配置向导,确保无头模式正常运行。 - 权限配置:Glue执行角色需要拥有S3读写权限、Glue作业执行权限,以及如果使用Bootstrap脚本,需要拥有访问yum源的权限。
内容的提问来源于stack exchange,提问作者roottraveller
相关产品推荐
相关产品推荐

