我已将SES配置为将一些电子邮件放入S3存储桶中,并设置S3触发器以在创建的对象上触发lambda函数。在lambda中,我需要解析和处理电子邮件。这是我的lambda(相关部分):
s3client = boto3.client('s3')
def lambda_handler(event, context):
my_bucket = s3.Bucket(‘xxxxxxxx')
my_key = event['Records'][0]['s3']['object']['key']
filename = '/tmp/'+ my_key
logger.info('Target file: ' + filename)
s3client.download_file(my_bucket, my_key, filename)
# Process email file
download_file引发异常:
expected string or bytes-like object: TypeError
Traceback (most recent call last):
File "/var/task/lambda_function.py", line 22, in lambda_handler
s3client.download_file(my_bucket, my_key, filename)
...
File "/var/runtime/botocore/handlers.py", line 217, in validate_bucket_name
if VALID_BUCKET.search(bucket) is None:
TypeError: expected string or bytes-like object
有什么想法吗?存储桶很好,存储桶中有对象。
答案 0 :(得分:1)
该错误与存储区名称有关(代码中有一个奇怪的弯引号)。
recommended检索对象详细信息的方法是:
for record in event['Records']:
bucket = record['s3']['bucket']['name']
key = record['s3']['object']['key']
...
s3_client.download_file(bucket, key, download_path)
答案 1 :(得分:0)
编辑:我的第一个答案可能是错误的,这是另一种尝试
可以找到引发异常的验证函数here
# From the S3 docs:
# The rules for bucket names in the US Standard region allow bucket names
# to be as long as 255 characters, and bucket names can contain any
# combination of uppercase letters, lowercase letters, numbers, periods
# (.), hyphens (-), and underscores (_).
VALID_BUCKET = re.compile(r'^[a-zA-Z0-9.\-_]{1,255}$')
# [I excluded unrelated code here]
def validate_bucket_name(params, **kwargs):
if 'Bucket' not in params:
return
bucket = params['Bucket']
if VALID_BUCKET.search(bucket) is None:
error_msg = (
'Invalid bucket name "%s": Bucket name must match '
'the regex "%s"' % (bucket, VALID_BUCKET.pattern))
raise ParamValidationError(report=error_msg)
boto3在后台使用S3Transfer下载管理器,然后使用download
方法定义为follows:
def download(self, bucket, key, fileobj, extra_args=None,
subscribers=None):
"""Downloads a file from S3
:type bucket: str
:param bucket: The name of the bucket to download from
...
它期望bucket
参数为字符串,并且您正在传递s3.Bucket(‘xxxxxxxx')
对象,该对象可能不是字符串。
我尝试将存储桶名称作为字符串传递给download_file
。
评论中指出的古老且最有可能的错误答案
一些sample code in the Boto Documentation向我们展示了如何执行从S3进行的下载:
import boto3
import botocore
BUCKET_NAME = 'my-bucket' # replace with your bucket name
KEY = 'my_image_in_s3.jpg' # replace with your object key
s3 = boto3.resource('s3')
try:
s3.Bucket(BUCKET_NAME).download_file(KEY, 'my_local_image.jpg')
except botocore.exceptions.ClientError as e:
if e.response['Error']['Code'] == "404":
print("The object does not exist.")
else:
raise
查看您的代码,好像您在以错误的方式调用download_file
方法,看起来应该像这样-您需要在Bucket-Object上调用该方法:
s3client = boto3.client('s3')
def lambda_handler(event, context):
my_bucket = s3.Bucket(‘xxxxxxxx')
my_key = event['Records'][0]['s3']['object']['key']
filename = '/tmp/'+ my_key
logger.info('Target file: ' + filename)
my_bucket.download_file(my_key, filename)
# Process email file
重要的部分是my_bucket.download_file(my_key, filename)