繁体   English   中英

Boto3 S3,按上次修改排序桶

[英]Boto3 S3, sort bucket by last modified

我需要使用 Boto3 从 S3 获取项目列表,但我希望它通过相反的顺序返回默认排序顺序(降序),而不是返回它。

我知道你可以通过 awscli 做到这一点:

aws s3api list-objects --bucket mybucketfoo --query "reverse(sort_by(Contents,&LastModified))"

并且可以通过 UI 控制台实现(不确定这是在客户端还是服务器端完成)

我似乎看不到如何在 Boto3 中执行此操作。

我目前正在获取所有文件,然后进行排序……但这似乎有些过分,尤其是当我只关心 10 个左右的最新文件时。

过滤系统似乎只接受 s3 的前缀,没有别的。

如果bucket中的对象不多,可以使用Python根据自己的需要进行排序。

定义一个 lambda 来获取最后修改时间:

get_last_modified = lambda obj: int(obj['LastModified'].strftime('%s'))

获取所有对象并按上次修改时间对它们进行排序。

s3 = boto3.client('s3')
objs = s3.list_objects_v2(Bucket='my_bucket')['Contents']
[obj['Key'] for obj in sorted(objs, key=get_last_modified)]

如果要反转排序:

[obj['Key'] for obj in sorted(objs, key=get_last_modified, reverse=True)]

我对@helloV 在下面发布的内容做了一些小改动。 它不是 100% 最佳的,但它完成了工作,但目前 boto3 有限制。

s3 = boto3.resource('s3')
my_bucket = s3.Bucket('myBucket')
unsorted = []
for file in my_bucket.objects.filter():
   unsorted.append(file)

files = [obj.key for obj in sorted(unsorted, key=get_last_modified, 
    reverse=True)][0:9]

似乎无法通过使用 boto3 进行排序。 根据文档,boto3 只支持集合的这些方法:

all(), filter(**kwargs), page_size(**kwargs), limit(**kwargs)

希望这在某种程度上有所帮助。 https://boto3.readthedocs.io/en/latest/reference/services/s3.html#S3.ServiceResource.buckets

以上略有改进:

import boto3

s3 = boto3.resource('s3')
my_bucket = s3.Bucket('myBucket')
files = my_bucket.objects.filter()
files = [obj.key for obj in sorted(files, key=lambda x: x.last_modified, 
    reverse=True)]

要获取 S3 中文件夹中最后修改的文件:

import boto3

s3 = boto3.resource('s3')
my_bucket = s3.Bucket('bucket_name')
files = my_bucket.objects.filter(Prefix='folder_name/subfolder_name/')
files = [obj.key for obj in sorted(files, key=lambda x: x.last_modified,
    reverse=True)][0:2]

print(files)

获取最后修改的两个文件:

files = [obj.key for obj in sorted(files, key=lambda x: x.last_modified,
    reverse=True)][0:2]

一种更简单的方法,使用 python3 sorted() 函数:

import boto3
s3 = boto3.resource('s3')

myBucket = s3.Bucket('name')

def obj_last_modified(myobj):
    return myobj.last_modified

sortedObjects = sorted(myBucket.objects.all(), key=obj_last_modified, reverse=True)

您现在有一个反向排序列表,按每个Object的 'last_modified' 属性排序。

keys = []

kwargs = {'Bucket': 'my_bucket'}
while True:
    resp = s3.list_objects_v2(**kwargs)
    for obj in resp['Contents']:
        keys.append(obj['Key'])

    try:
        kwargs['ContinuationToken'] = resp['NextContinuationToken']
    except KeyError:
        break

这将使您按排序顺序获得所有键


s3 = boto3.client('s3')

get_last_modified = lambda obj: int(obj['LastModified'].strftime('%Y%m%d%H%M%S'))

def sortFindLatest(bucket_name):
    resp = s3.list_objects(Bucket=bucket_name)
    if 'Contents' in resp:
        objs = resp['Contents']
        files = sorted(objs, key=get_last_modified)
        for key in files:
            file = key['Key']
            cx = s3.get_object(Bucket=bucket_name, Key=file)

这对我来说可以按日期和时间排序。 我正在使用 Python3 AWS lambda。 您的里程可能会有所不同。 它可以优化,我特意让它离散。 正如之前的帖子中提到的,可以添加“reverse=True”来更改排序顺序。

所以我的回答可用于上次修改,但我认为如果您来到此页面,您可能希望能够以其他方式对文件进行排序。 所以用一块石头杀死 2 只鸟:

在此线程中,您可以找到内置方法sorted 如果您阅读文档或这篇文章,您会发现您可以创建自己的 function 来优先考虑对象的排序方式。 因此,例如在我的情况下。 我有一堆文件,前面有一些数字,可能还有一封信。 它看起来像这样:

1.svg
10.svg
100a.svg
11.svg
110.svg
...
2.svg
20b.svg
200.svg
...
10011b.svg
...
etc

我希望它按前面的数字排序——我不关心数字后面的字母,所以我写了这个 function:

def my_sort(x):
    try:
        # this will take the file name, split over the file type and take just the name, cast it to an int, and return it
        return int(x.split(".")[0])
    # if it couldn't do that
    except ValueError:
        # it will take the file name, split it over the extension, and take the name
        n = x.split(".")[0]
        s = ""
        # then for each character
        for e in n:
            # check to see if it is a digit and append it to a string if it is
            if e.isdigit():
                s += e
            # if its not a digit, it hit the character at the end of the name, so return it
            else:
                return int(s)

这意味着现在我可以这样做:

import boto3
s3r = boto3.resource('s3')
bucket = s3r.Bucket('my_bucket')
os = bucket.objects.filter(Prefix="my_prefix/")
os = [o.key.split("/")[-1] for o in os]
os = sorted(os, key=my_sort)

# do whatever with the sorted data

这将按名称中的数字后缀对我的文件进行排序。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM