Python boto,列出桶中特定目录的内容

Posted

技术标签:

【中文标题】Python boto,列出桶中特定目录的内容【英文标题】:Python boto, list contents of specific dir in bucket 【发布时间】:2015-02-02 05:19:07 【问题描述】:

我只能通过 S3 访问 S3 存储桶中的特定目录。

例如,如果我尝试列出整个存储桶,则使用 s3cmd 命令:

    $ s3cmd ls s3://bucket-name

我收到一个错误:Access to bucket 'my-bucket-url' was denied

但是如果我尝试访问存储桶中的特定目录,我可以看到内容:

    $ s3cmd ls s3://bucket-name/dir-in-bucket

现在我想用 python boto 连接到 S3 存储桶。类似:

    bucket = conn.get_bucket('bucket-name')

我收到一个错误:boto.exception.S3ResponseError: S3ResponseError: 403 Forbidden

但如果我尝试:

    bucket = conn.get_bucket('bucket-name/dir-in-bucket')

脚本暂停大约 10 秒,然后打印出错误。波纹管是完整的跟踪。知道如何进行吗?

注意问题是关于 boto 版本 2 模块,而不是 boto3。

Traceback (most recent call last):
  File "test_s3.py", line 7, in <module>
    bucket = conn.get_bucket('bucket-name/dir-name')
  File "/usr/local/lib/python2.7/dist-packages/boto/s3/connection.py", line 471, in get_bucket
    return self.head_bucket(bucket_name, headers=headers)
  File "/usr/local/lib/python2.7/dist-packages/boto/s3/connection.py", line 490, in head_bucket
    response = self.make_request('HEAD', bucket_name, headers=headers)
  File "/usr/local/lib/python2.7/dist-packages/boto/s3/connection.py", line 633, in make_request
    retry_handler=retry_handler
  File "/usr/local/lib/python2.7/dist-packages/boto/connection.py", line 1046, in make_request
    retry_handler=retry_handler)
  File "/usr/local/lib/python2.7/dist-packages/boto/connection.py", line 922, in _mexe
    request.body, request.headers)
  File "/usr/lib/python2.7/httplib.py", line 958, in request
    self._send_request(method, url, body, headers)
  File "/usr/lib/python2.7/httplib.py", line 992, in _send_request
    self.endheaders(body)
  File "/usr/lib/python2.7/httplib.py", line 954, in endheaders
    self._send_output(message_body)
  File "/usr/lib/python2.7/httplib.py", line 814, in _send_output
    self.send(msg)
  File "/usr/lib/python2.7/httplib.py", line 776, in send
    self.connect()
  File "/usr/lib/python2.7/httplib.py", line 1157, in connect
    self.timeout, self.source_address)
  File "/usr/lib/python2.7/socket.py", line 553, in create_connection
    for res in getaddrinfo(host, port, 0, SOCK_STREAM):
socket.gaierror: [Errno -2] Name or service not known

【问题讨论】:

也许您应该在脚本中使用my-bucket-url/dir-in-bucket 而不是my-bucket-url/my-bucket-url 抱歉,在尝试删除实际存储桶和目录名称时出现错误。 【参考方案1】:

对于boto3

import boto3

s3 = boto3.resource('s3')
my_bucket = s3.Bucket('my_bucket_name')

for object_summary in my_bucket.objects.filter(Prefix="dir_name/"):
    print(object_summary.key)

【讨论】:

您必须在 object_summary.key 周围使用大括号才能在 python3 中工作。打印(object_summary.key)【参考方案2】:

默认情况下,当您在 boto 中调用 get_bucket 时,它会尝试通过对存储桶 URL 执行 HEAD 请求来验证您是否确实有权访问该存储桶。在这种情况下,您不希望 boto 这样做,因为您无权访问存储桶本身。所以,这样做:

bucket = conn.get_bucket('my-bucket-url', validate=False)

然后你应该能够做这样的事情来列出对象:

for key in bucket.list(prefix='dir-in-bucket'): 
    <do something>

如果仍然出现 403 错误,请尝试在前缀末尾添加斜杠。

for key in bucket.list(prefix='dir-in-bucket/'): 
    <do something>

注意:这个答案是关于 boto version 2 模块的,现在已经过时了。目前(2020 年),boto3 是使用 AWS 的标准模块。有关更多信息,请参阅此问题:What is the difference between the AWS boto and boto3

【讨论】:

谢谢,这对我有用,我只需要在存储桶名称的末尾添加一个斜杠('/'),否则我仍然收到 403 错误。 是的,这是有道理的。我批准了您对我的示例的编辑。很高兴它为你工作。 为什么需要尾随“/”?我可以确认它在我的实例中是必需的,但我找不到它的文档。【参考方案3】:

Boto3 客户端:

import boto3

_BUCKET_NAME = 'mybucket'
_PREFIX = 'subfolder/'

client = boto3.client('s3', aws_access_key_id=ACCESS_KEY,
                            aws_secret_access_key=SECRET_KEY)

def ListFiles(client):
    """List files in specific S3 URL"""
    response = client.list_objects(Bucket=_BUCKET_NAME, Prefix=_PREFIX)
    for content in response.get('Contents', []):
        yield content.get('Key')

file_list = ListFiles(client)
for file in file_list:
    print 'File found: %s' % file

使用会话

from boto3.session import Session

_BUCKET_NAME = 'mybucket'
_PREFIX = 'subfolder/'

session = Session(aws_access_key_id=ACCESS_KEY,
                  aws_secret_access_key=SECRET_KEY)

client = session.client('s3')

def ListFilesV1(client, bucket, prefix=''):
    """List files in specific S3 URL"""
    paginator = client.get_paginator('list_objects')
    for result in paginator.paginate(Bucket=bucket, Prefix=prefix,
                                     Delimiter='/'):
        for content in result.get('Contents', []):
            yield content.get('Key')

file_list = ListFilesV1(client, _BUCKET_NAME, prefix=_PREFIX)
for file in file_list:
    print 'File found: %s' % file

【讨论】:

一般来说:基于 boto3.resource 或 boto3.cleint 或 boto3.session 的方法有什么区别,在什么条件下应遵循哪种方法? 对于任何混淆,boto3.resource 是首选。这里还有客户端和资源之间的区别:***.com/questions/42809096/…【参考方案4】:

我也遇到了同样的问题,这段代码可以解决问题。

import boto3

s3 = boto3.resource("s3")
s3_bucket = s3.Bucket("bucket-name")
dir = "dir-in-bucket"
files_in_s3 = [f.key.split(dir + "/")[1] for f in 
s3_bucket.objects.filter(Prefix=dir).all()]

【讨论】:

这个答案涉及 boto3,原来的问题是针对 boto 版本 2 模块的。尽管如此,到 2020 年,boto3 已经成为标准【参考方案5】:

以下代码将列出 S3 存储桶特定目录中的所有文件:

import boto3

s3 = boto3.client('s3')

def get_all_s3_keys(s3_path):
    """
    Get a list of all keys in an S3 bucket.

    :param s3_path: Path of S3 dir.
    """
    keys = []

    if not s3_path.startswith('s3://'):
        s3_path = 's3://' + s3_path

    bucket = s3_path.split('//')[1].split('/')[0]
    prefix = '/'.join(s3_path.split('//')[1].split('/')[1:])

    kwargs = 'Bucket': bucket, 'Prefix': prefix
    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

    return keys

【讨论】:

【参考方案6】:

这可以使用:

s3_client = boto3.client('s3')
objects = s3_client.list_objects_v2(Bucket='bucket_name')
for obj in objects['Contents']:
  print(obj['Key'])

【讨论】:

【参考方案7】:

如果要列出存储桶中某个文件夹的所有对象,可以在列出时指定。

import boto
conn = boto.connect_s3(AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY)
bucket = conn.get_bucket(AWS_BUCKET_NAME)
for file in bucket.list("FOLDER_NAME/", "/"):
    <do something with required file>

【讨论】:

OP 提到 get_bucket 给了他一个 403 如何将一个特定文件的内容读取到一个变量中? @Rahul 我猜 file.read() 应该可以工作。但是我必须检查一次。 @ChrisWue 这可能是因为错误的秘密访问密钥 OP 对存储桶中的文件或文件夹具有特定访问权限,但无权访问存储桶。我处于同样的位置,我可以访问 AWS GUI 中的文件和文件夹,但我无法在 boto3 中完成任何操作。

以上是关于Python boto,列出桶中特定目录的内容的主要内容,如果未能解决你的问题,请参考以下文章

使用 boto3 列出存储桶的内容

使用 boto3 检查 s3 的存储桶中是不是存在密钥

列出 Amazon S3 存储桶中所有文件的快速方法?

使用Python boto3上传Windows EC2实例中的文件至S3存储桶中

Amazon S3 boto:如何重命名存储桶中的文件?

AWS BOTO3 S3 python - 调用 HeadObject 操作时发生错误(404):未找到