这就是我如何在 Lambda 上建立并运行表格。我使用了Lambda的OCI能力来打包需求。
首先,我使用 VSCode 创建文件夹结构来放置 lambda 函数和 Docker 文件。
我创建了一个名为“lambda_function.py”的文件,其中包含上面列出的代码。我创建了一个 pip requests.txt 文件,其中包含以下库(您不应该使用它,而应该使用固定版本,我这样做只是为了速度)
我确实必须更改您的代码,并且我进行了以下更改(导入语句)
import json
import boto3
import pandas as pd
import io
import re
from tabula.io import read_pdf
import numpy as np
..
..
因为我收到错误“AttributeError: module 'tabula' has no attribute 'read_pdf'”
pandas
numpy
tabula-py
boto3
然后我创建了我的 Docker 文件(非常粗糙,没有优化,只是为了引导它并让它运行 - 你肯定想改进它)
FROM public.ecr.aws/lambda/python:3.10
COPY requirements.txt ${LAMBDA_TASK_ROOT}
COPY lambda_function.py ${LAMBDA_TASK_ROOT}
RUN yum install java-17-amazon-corretto-devel -y
RUN pip install --upgrade pip
RUN pip install --no-cache-dir -r requirements.txt
CMD [ "lambda_function.lambda_handler" ]
这就是我的布局:
├── Dockerfile
├── lambda_function.py
└── requirements.txt
然后,我运行以下命令在本地构建容器映像,然后将其上传到亚马逊 ecr(我创建了一个 ecr 存储库)
docker build -t lambda-tabula:1.0.0 .
aws ecr get-login-password --region eu-west-1 | docker login --username AWS --password-stdin xxxx.dkr.ecr.eu-west-1.amazonaws.com
docker tag lambda-tabula:1.0.0 xxxx.dkr.ecr.eu-west-1.amazonaws.com/lambda-oci-demo:1.0.1
docker push xxxx.dkr.ecr.eu-west-1.amazonaws.com/lambda-oci-demo:1.0.1
我现在在 ECR 中有我的图像,我可以通过 arn 引用它(“xxxxx.dkr.ecr.eu-west-1.amazonaws.com/lambda-oci-demo:1.0.0”)
然后,我创建了一个新的 Lambda 函数,指定 OCI 图像,然后指向该图像。我为该函数创建了一个角色,该角色也将提供对此特定 S3 存储桶的权限。
您可以在以下位置获取更多详细信息文档在这里 https://docs.aws.amazon.com/lambda/latest/dg/python-image.html
这允许该函数运行,尽管由于当前函数想要写入只读文件系统而失败并出现不同的错误,因此我将 name_of_return_file = f'{file_name[:-4]}_return.csv' 更改为 name_of_return_file = f'/tmp/{file_name[:-4]}_return.csv'
一旦我解决了这个问题,效果就很好。这是更新后的代码
import json
import boto3
import pandas as pd
import io
import re
from tabula.io import read_pdf
import numpy as np
def f_remove_accents(old):
new = old.lower()
new = re.sub(r'[àáâãäå]', 'a', new)
new = re.sub(r'[èéêë]', 'e', new)
new = re.sub(r'[ìíîï]', 'i', new)
new = re.sub(r'[òóôõö]', 'o', new)
new = re.sub(r'[ùúûü]', 'u', new)
new = re.sub(r'[ç]', 'c', new)
return new
def lambda_handler(event, context):
s3 = boto3.client("s3")
if event:
#s3_records = event["Records"][0]
#bucket_name = str(s3_records["s3"]["bucket"]["name"])
#file_name = str(s3_records["s3"]["object"]["key"])
#file_obj = s3.get_object(Bucket=bucket_name, Key=file_name)
file_obj = s3.get_object(Bucket="tabula-demo", Key="invoice.pdf")
file_content = file_obj["Body"].read()
tables = read_pdf(io.BytesIO(file_content), pages='all')
# Create an empty DataFrame to store all the modified tables
modified_tables = []
# Apply functions to the content of each table
for table in tables:
# Convert the DataFrame to a NumPy array
table_array = table.values.astype(str)
# Remove accents
remove_accents_func = np.vectorize(f_remove_accents)
table_array = remove_accents_func(table_array)
# Replace ';' with ' '
table_array = np.char.replace(table_array, ';', ' ')
# Convert to upper case
table_array = np.char.upper(table_array)
# Create a new DataFrame with the modified array
modified_table = pd.DataFrame(table_array, columns=table.columns)
# Append the modified table to the list
modified_tables.append(modified_table)
# Concatenate all the modified tables into a single DataFrame
final_df = pd.concat(modified_tables, ignore_index=True)
# Save the final DataFrame as a CSV file
#name_of_return_file = f'{file_name[:-4]}_return.csv'
name_of_return_file = '/tmp/test_return.csv'
final_df.to_csv(name_of_return_file, sep=';', index=False)
# Read the CSV file content
with open(name_of_return_file, 'rb') as file:
csv_content = file.read()
# Upload the CSV file to the destination bucket
s3.put_object(Body=csv_content, Bucket='094459-lambda-libs', Key=name_of_return_file)
笔记!我必须修改上面的代码,因为我对文件进行了硬编码,因为我不知道您的输入文件是什么。