2014-07-08 10 views
6

Uso il boto S3 API nel mio script python che lentamente copia i dati da S3 al mio filesystem locale. La sceneggiatura ha funzionato bene per un paio di giorni, ma ora c'è un problema.L'API Boto S3 non restituisce l'elenco completo delle chiavi

Io uso la seguente funzione API per ottenere l'elenco di chiavi in ​​"directory":

keys = bucket.get_all_keys(prefix=dirname) 

E questa funzione (get_all_keys) non restituisce sempre l'elenco completo di chiavi, voglio dire che posso vedere di più chiavi attraverso l'interfaccia web AWS o tramite aws s3 ls s3://path.

Riprodotto il problema sulle versioni 2.15 e 2.30.

Forse boto ha memorizzato alcune delle mie richieste su S3 (ripeto le stesse richieste più e più volte)? Come risolvere questo problema, qualche suggerimento?

risposta

12

C'è un modo più semplice. L'oggetto Bucket può agire da iteratore e sa come gestire le risposte impaginate. Quindi, se ci sono più risultati disponibili, li recupererà automaticamente dietro le quinte. Quindi, qualcosa di simile a questo dovrebbe consentire di iterazioni su tutti gli oggetti nel secchio:

for key in bucket: 
    # do something with your key 

Se si desidera specificare un prefisso e ottenere un elenco di tutte le chiavi che iniziano con quel prefisso, è possibile farlo come questo:

for key in bucket.list(prefix='foobar'): 
    # do something with your key 

Oppure, se davvero, vuole veramente costruire un elenco di oggetti, solo fare questo:

keys = [k for k in bucket] 

si noti, tuttavia, che secchi può contenere un numero illimitato di chiavi, in modo essere carefu l con questo perché costruirà una lista di tutte le chiavi in ​​memoria.

+0

come elencare le chiavi con particolare prefisso –

+1

Appena aggiornato la risposta con un esempio. – garnaat

5

Appena riuscito a farlo funzionare! Si è scoperto che avevo 1013 chiavi nella mia directory su S3 e get_all_keys può restituire solo 1000 chiavi a causa delle restrizioni dell'API AWS.

La soluzione è semplice, basta utilizzare più funzione di alto livello senza delimiter parametro:

keys = list(bucket.list(prefix=dirname)) 
3

È necessario impaginare i risultati, effettuando più richieste. list() lo farà automaticamente. È possibile utilizzare l'esempio seguente per un controllo maggiore o per riprendere da richieste non riuscite.

Questo approccio iterativo è anche più scalabile se si lavora milioni di oggetti.

marker = None 
while True: 
    keys = bucket.get_all_keys(marker=marker) 
    last_key = None 

    for k in keys: 
     # TODO Do something with your keys! 
     last_key = k.name 

    if not keys.is_truncated: 
     break 

    marker = last_key 

Il ResultSet docs dal get_all_keys() docs dicono che questo dovrebbe essere fatto autoamtically dal per iteratore, ma non è così. . :(

1

Utilizzare la paginazione in boto3 questa funzione dovrebbe dare la risposta:?

def s3_list_files(bucket_name, prefix): 
    paginator = client.get_paginator("list_objects") 

    page_iterator = paginator.paginate(Bucket=bucket_name, Prefix=prefix) 
    keys = [] 
    for page in page_iterator: 
     if "Contents" in page: 
      for key in page["Contents"]: 
       keyString = key["Key"] 
       keys.append(keyString) 

    return keys if keys else [] 
Problemi correlati