Mendaftar isi ember dengan boto3


198

Bagaimana saya bisa melihat apa yang ada di dalam ember dengan S3 boto3? (yaitu melakukan "ls")?

Melakukan hal berikut:

import boto3
s3 = boto3.resource('s3')
my_bucket = s3.Bucket('some/path/')

pengembalian:

s3.Bucket(name='some/path/')

Bagaimana saya melihat isinya?

Jawaban:


241

Salah satu cara untuk melihat isinya adalah:

for my_bucket_object in my_bucket.objects.all():
    print(my_bucket_object)

1
dapatkah saya mengambil kunci di bawah jalur tertentu dalam ember atau dengan pembatas khusus menggunakan boto3 ??
Rahul KP

109
Anda harus bisa mengatakan mybucket.objects.filter(Prefix='foo/bar')dan itu hanya akan mendaftar objek dengan awalan itu. Anda juga dapat melewati Delimiterparameter.
garnaat

3
tidak bekerja dengan boto3 AttributeError: objek 'S3' tidak memiliki atribut 'objek'
Shek

2
@ garnaat Komentar Anda menyebutkan bahwa metode filter sangat membantu saya (kode saya berakhir lebih sederhana dan lebih cepat) - terima kasih!
Edward Dixon

24
Saya akan menyarankan agar tidak menggunakan objectnama variabel karena akan membayangi tipe global object.
oliland

100

Ini mirip dengan 'ls' tetapi tidak memperhitungkan konvensi folder awalan dan akan mencantumkan objek dalam ember. Terserah kepada pembaca untuk menyaring awalan yang merupakan bagian dari nama Kunci.

Dengan Python 2:

from boto.s3.connection import S3Connection

conn = S3Connection() # assumes boto.cfg setup
bucket = conn.get_bucket('bucket_name')
for obj in bucket.get_all_keys():
    print(obj.key)

Dengan Python 3:

from boto3 import client

conn = client('s3')  # again assumes boto.cfg setup, assume AWS S3
for key in conn.list_objects(Bucket='bucket_name')['Contents']:
    print(key['Key'])

39
Jika Anda ingin menggunakan awalan juga, Anda dapat melakukannya seperti ini:conn.list_objects(Bucket='bucket_name', Prefix='prefix_string')['Contents']
markonovak

13
Ini hanya mencantumkan 1.000 kunci pertama. Dari docstring: "Mengembalikan beberapa atau semua (hingga 1000) objek dalam ember." Selain itu, Anda disarankan untuk menggunakan list_objects_v2 alih-alih list_objects (walaupun, ini juga hanya mengembalikan 1000 kunci pertama).
Brett Widmeier

3
Batasan ini harus ditangani dengan menggunakan Paginators
v25

44

Saya berasumsi Anda telah mengkonfigurasi otentikasi secara terpisah.

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

my_bucket = s3.Bucket('bucket_name')

for file in my_bucket.objects.all():
    print(file.key)

30

Jika Anda ingin meneruskan kunci ACCESS dan SECRET (yang seharusnya tidak Anda lakukan, karena tidak aman):

from boto3.session import Session

ACCESS_KEY='your_access_key'
SECRET_KEY='your_secret_key'

session = Session(aws_access_key_id=ACCESS_KEY,
                  aws_secret_access_key=SECRET_KEY)
s3 = session.resource('s3')
your_bucket = s3.Bucket('your_bucket')

for s3_file in your_bucket.objects.all():
    print(s3_file.key)

13
Ini kurang aman daripada memiliki file kredensial di ~ / .aws / kredensial. Padahal itu solusi yang valid.
nu everest

6
Ini akan memerlukan melakukan rahasia ke kontrol sumber. Tidak baik.
jan groth

2
Jawaban ini tidak menambahkan apa pun mengenai API / mekanisme daftar objek sambil menambahkan metode otentikasi yang tidak relevan yang umum untuk semua sumber daya boto dan merupakan praktik buruk dalam hal keamanan
Froyke

Menambahkan penafian atas jawaban tentang keamanan.
rjurney

Bagaimana jika kunci dipasok oleh sistem manajemen kunci / rahasia seperti Vault (Hashicorp) - bukankah itu lebih baik daripada hanya menempatkan file kredensial di ~ / .aws / kredensial?
SunnyAk

25

Untuk menangani daftar kunci yang besar (yaitu ketika daftar direktori lebih besar dari 1000 item), saya menggunakan kode berikut untuk mengumpulkan nilai-nilai kunci (yaitu nama file) dengan banyak daftar (terima kasih kepada Amelio di atas untuk baris pertama). Kode untuk python3:

    from boto3  import client
    bucket_name = "my_bucket"
    prefix      = "my_key/sub_key/lots_o_files"

    s3_conn   = client('s3')  # type: BaseClient  ## again assumes boto.cfg setup, assume AWS S3
    s3_result =  s3_conn.list_objects_v2(Bucket=bucket_name, Prefix=prefix, Delimiter = "/")

    if 'Contents' not in s3_result:
        #print(s3_result)
        return []

    file_list = []
    for key in s3_result['Contents']:
        file_list.append(key['Key'])
    print(f"List count = {len(file_list)}")

    while s3_result['IsTruncated']:
        continuation_key = s3_result['NextContinuationToken']
        s3_result = s3_conn.list_objects_v2(Bucket=bucket_name, Prefix=prefix, Delimiter="/", ContinuationToken=continuation_key)
        for key in s3_result['Contents']:
            file_list.append(key['Key'])
        print(f"List count = {len(file_list)}")
    return file_list

20

Fungsi utilitas s3keys saya pada dasarnya adalah versi optimal dari jawaban @ Hephaestus:

import boto3


s3_paginator = boto3.client('s3').get_paginator('list_objects_v2')


def keys(bucket_name, prefix='/', delimiter='/', start_after=''):
    prefix = prefix[1:] if prefix.startswith(delimiter) else prefix
    start_after = (start_after or prefix) if prefix.endswith(delimiter) else start_after
    for page in s3_paginator.paginate(Bucket=bucket_name, Prefix=prefix, StartAfter=start_after):
        for content in page.get('Contents', ()):
            yield content['Key']

Dalam pengujian saya (boto3 1.9.84), ini secara signifikan lebih cepat daripada kode yang setara (tetapi lebih sederhana):

import boto3


def keys(bucket_name, prefix='/', delimiter='/'):
    prefix = prefix[1:] if prefix.startswith(delimiter) else prefix
    bucket = boto3.resource('s3').Bucket(bucket_name)
    return (_.key for _ in bucket.objects.filter(Prefix=prefix))

Karena S3 menjamin hasil penyortiran biner UTF-8 , start_afteroptimasi telah ditambahkan ke fungsi pertama.


Sejauh ini, inilah jawaban terbaik. Saya baru saja memodifikasi jawaban @ Hephaestus (karena itu adalah yang tertinggi) ketika saya menggulir ke bawah. Ini harus menjadi jawaban yang diterima dan harus mendapatkan poin tambahan karena ringkas. Saya akan menambahkan bahwa generator dari kode kedua perlu dibungkus list()untuk mengembalikan daftar file.
Richard D

@ Richard keduanya menghasilkan generator. Banyak ember yang saya targetkan dengan kode ini memiliki lebih banyak kunci daripada yang dapat ditangani oleh pelaksana kode sekaligus (misalnya, AWS Lambda); Saya lebih suka mengkonsumsi kunci karena dihasilkan.
Sean Summers

6

Cara yang lebih pelit, alih-alih iterasi melalui perulangan for Anda juga bisa mencetak objek asli yang berisi semua file di dalam bucket S3 Anda:

session = Session(aws_access_key_id=aws_access_key_id,aws_secret_access_key=aws_secret_access_key)
s3 = session.resource('s3')
bucket = s3.Bucket('bucket_name')

files_in_s3 = bucket.objects.all() 
#you can print this iterable with print(list(files_in_s3))

3
@ petezurich, bisakah Anda menjelaskan mengapa suntingan kecil jawaban saya - mengganti "a" dengan huruf kapital "A" di awal jawaban saya menurunkan reputasi saya dengan -2, namun saya rasa Anda dan saya bisa setuju itu bukan saja koreksi Anda TIDAK relevan sama sekali, tetapi sebenarnya agak sepele, bukankah Anda akan mengatakannya? Harap fokus pada konten daripada revisi kekanak-kanakan, ol'boy paling wajib
Daniel Vieira

Ini adalah dua interaksi yang berbeda. 1. Saya mengedit jawaban Anda yang direkomendasikan bahkan untuk kesalahan ejaan kecil. Saya setuju, bahwa batas-batas antara minor dan sepele bersifat ambigu. Saya tidak mengunduh pesan apa pun karena saya melihat kesalahan dan saya tidak melakukannya. Saya hanya memperbaiki semua kesalahan yang saya lihat.
petezurich

2. Saya menurunkan jawaban Anda karena Anda menulis itu files_in_s3adalah "daftar objek". Tidak ada hal seperti itu di Python. Ini lebih merupakan iterable dan saya tidak bisa membuat kode Anda bekerja dan karenanya downvoted. Daripada saya menemukan kesalahan dan melihat maksud Anda tetapi tidak bisa membatalkan downvote saya.
petezurich

5
@ petezurich tidak ada masalah, mengerti, titik, hanya satu hal Anda, dalam Python daftar ADALAH objek karena hampir semua yang ada di python adalah objek, maka itu juga mengikuti bahwa daftar juga merupakan iterable, tapi pertama dan terutama, ini adalah obyek! itu sebabnya saya tidak mengerti downvote Anda - Anda memilih sesuatu yang benar dan kode yang berfungsi. Bagaimanapun, terima kasih atas permintaan maaf Anda dan semua yang terbaik
Daniel Vieira

1
@Petezurich Segala sesuatu di Python adalah objek. "Daftar objek" sepenuhnya dapat diterima.
Zach Garwood

4

Ringkasan Obyek:

Ada dua pengidentifikasi yang dilampirkan ke Ringkasan ObjectSum:

  • bucket_name
  • kunci

boto3 S3: ObjectSummary

Lebih lanjut tentang Kunci Objek dari Dokumentasi AWS S3:

Kunci Objek:

Saat Anda membuat objek, Anda menentukan nama kunci, yang secara unik mengidentifikasi objek dalam ember. Misalnya, di konsol Amazon S3 (lihat AWS Management Console), ketika Anda menyorot sebuah ember, daftar objek dalam ember Anda muncul. Nama-nama ini adalah kunci objek. Nama untuk kunci adalah urutan karakter Unicode yang pengkodean UTF-8 paling panjang 1024 byte.

Model data Amazon S3 adalah struktur datar: Anda membuat ember, dan ember menyimpan objek. Tidak ada hierarki subbucket atau subfolder; Namun, Anda dapat menyimpulkan hierarki logis menggunakan awalan nama kunci dan pembatas seperti yang dilakukan konsol Amazon S3. Konsol Amazon S3 mendukung konsep folder. Misalkan ember Anda (dibuat admin) memiliki empat objek dengan kunci objek berikut:

Pengembangan / Projects1.xls

Keuangan / statement1.pdf

Pribadi / taxdocument.pdf

s3-dg.pdf

Referensi:

AWS S3: Tombol Objek

Berikut ini beberapa contoh kode yang menunjukkan cara mendapatkan nama bucket dan kunci objek.

Contoh:

import boto3
from pprint import pprint

def main():

    def enumerate_s3():
        s3 = boto3.resource('s3')
        for bucket in s3.buckets.all():
             print("Name: {}".format(bucket.name))
             print("Creation Date: {}".format(bucket.creation_date))
             for object in bucket.objects.all():
                 print("Object: {}".format(object))
                 print("Object bucket_name: {}".format(object.bucket_name))
                 print("Object key: {}".format(object.key))

    enumerate_s3()


if __name__ == '__main__':
    main()

3

Saya baru saja melakukannya seperti ini, termasuk metode otentikasi:

s3_client = boto3.client(
                's3',
                aws_access_key_id='access_key',
                aws_secret_access_key='access_key_secret',
                config=boto3.session.Config(signature_version='s3v4'),
                region_name='region'
            )

response = s3_client.list_objects(Bucket='bucket_name', Prefix=key)
if ('Contents' in response):
    # Object / key exists!
    return True
else:
    # Object / key DOES NOT exist!
    return False

2
#To print all filenames in a bucket
import boto3

s3 = boto3.client('s3')

def get_s3_keys(bucket):

    """Get a list of keys in an S3 bucket."""
    resp = s3.list_objects_v2(Bucket=bucket)
    for obj in resp['Contents']:
      files = obj['Key']
    return files


filename = get_s3_keys('your_bucket_name')

print(filename)

#To print all filenames in a certain directory in a bucket
import boto3

s3 = boto3.client('s3')

def get_s3_keys(bucket, prefix):

    """Get a list of keys in an S3 bucket."""
    resp = s3.list_objects_v2(Bucket=bucket, Prefix=prefix)
    for obj in resp['Contents']:
      files = obj['Key']
      print(files)
    return files


filename = get_s3_keys('your_bucket_name', 'folder_name/sub_folder_name/')

print(filename)

Kedua "get_s3_keys" hanya mengembalikan kunci terakhir.
Alexey Vazhnov

Ini mencantumkan semua file dalam ember; pertanyaannya adalah bagaimana melakukan ls. Bagaimana Anda melakukan itu..hanya mencetak file di root
Herman

1

Dengan sedikit modifikasi pada kode @Hephaeastus di salah satu komentar di atas, tulis metode di bawah ini untuk membuat daftar folder dan objek (file) di jalur yang diberikan. Bekerja mirip dengan perintah s3 ls.

from boto3 import session

def s3_ls(profile=None, bucket_name=None, folder_path=None):
    folders=[]
    files=[]
    result=dict()
    bucket_name = bucket_name
    prefix= folder_path
    session = boto3.Session(profile_name=profile)
    s3_conn   = session.client('s3')
    s3_result =  s3_conn.list_objects_v2(Bucket=bucket_name, Delimiter = "/", Prefix=prefix)
    if 'Contents' not in s3_result and 'CommonPrefixes' not in s3_result:
        return []

    if s3_result.get('CommonPrefixes'):
        for folder in s3_result['CommonPrefixes']:
            folders.append(folder.get('Prefix'))

    if s3_result.get('Contents'):
        for key in s3_result['Contents']:
            files.append(key['Key'])

    while s3_result['IsTruncated']:
        continuation_key = s3_result['NextContinuationToken']
        s3_result = s3_conn.list_objects_v2(Bucket=bucket_name, Delimiter="/", ContinuationToken=continuation_key, Prefix=prefix)
        if s3_result.get('CommonPrefixes'):
            for folder in s3_result['CommonPrefixes']:
                folders.append(folder.get('Prefix'))
        if s3_result.get('Contents'):
            for key in s3_result['Contents']:
                files.append(key['Key'])

    if folders:
        result['folders']=sorted(folders)
    if files:
        result['files']=sorted(files)
    return result

Ini daftar semua objek / folder di jalur yang diberikan. Folder_path dapat dibiarkan sebagai Tidak Ada secara default dan metode akan mendaftar konten langsung dari akar ember.


0

Ini solusinya

impor boto3

s3 = boto3.resource ('s3')

BUCKET_NAME = 'Nama Ember S3 Anda eg'deletemetesting11' '

allFiles = s3.Bucket (BUCKET_NAME) .objects.all ()

untuk file di allFiles: print (file.key)


0

Dapat juga dilakukan sebagai berikut:

csv_files = s3.list_objects_v2(s3_bucket_path)
    for obj in csv_files['Contents']:
        key = obj['Key']

0

Jadi Anda meminta yang setara dengan aws s3 lsdi boto3. Ini akan membuat daftar semua folder dan file tingkat atas. Ini adalah yang terdekat yang bisa saya dapatkan; hanya mencantumkan semua folder tingkat atas. Mengejutkan betapa sulitnya operasi sederhana itu.

import boto3

def s3_ls():
  s3 = boto3.resource('s3')
  bucket = s3.Bucket('example-bucket')
  result = bucket.meta.client.list_objects(Bucket=bucket.name,
                                           Delimiter='/')
  for o in result.get('CommonPrefixes'):
    print(o.get('Prefix'))
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.