簡體   English   中英

如何使用 Python 和 boto3 將多個文件附加到 Amazon 的 s3 中?

[英]How to append multiple files into one in Amazon's s3 using Python and boto3?

我在亞馬遜的 S3 中有一個名為test-bucket 在這個存儲桶中,json 文件如下所示:

test-bucket
    | continent
        | country
            | <filename>.json

本質上,文件名是continent/country/name/ 在每個國家/地區,大約有 100k 個文件,每個文件包含一個字典,如下所示:

{"data":"more data", "even more data":"more data", "other data":"other other data"}

不同的文件有不同的長度。 我需要做的是將所有這些文件編譯成一個文件,然后將該文件重新上傳到 s3。 簡單的解決方案是使用 boto3 下載所有文件,將它們讀入 Python,然后使用以下腳本附加它們:

import json


def append_to_file(data, filename):
    with open(filename, "a") as f:
        json.dump(record, f)
        f.write("\n")

但是,我不知道所有文件名(名稱是時間戳)。 如何讀取文件夾中的所有文件,例如Asia/China/* ,然后將它們附加到文件中,文件名是國家?

最理想的是,我不想將所有文件下載到本地存儲中。 如果我可以將這些文件加載​​到內存中,那就太好了。

編輯:讓事情更清楚。 s3 上的文件不存儲在文件夾中,文件路徑只是設置為看起來像一個文件夾。 所有文件都存儲在test-bucket

答案很簡單。 您可以使用過濾器列出存儲桶中的所有文件,將其過濾到前綴中的“子目錄”。 如果你事先有一個大洲和國家的列表,那么你可以減少返回的列表。 返回的列表將具有前綴,因此您可以將對象名稱列表過濾為您想要的名稱。

    s3 = boto3.resource('s3')
    bucket_obj = s3.Bucket(bucketname)

    all_s3keys = list(obj.key for obj in bucket_obj.objects.filter(Prefix=job_prefix))

    if file_pat:
        filtered_s3keys = [key for key in all_s3keys if bool(re.search(file_pat, key))]
    else:
        filtered_s3keys = all_s3keys

上面的代碼將返回所有文件,以及它們在存儲桶中的完整前綴,不包括提供的前綴。 因此,如果您提供 prefix='Asia/China/',那么它將僅提供具有該前綴的文件列表。 在某些情況下,在使用完整前綴訪問文件之前,我會采取第二步並過濾該“子目錄”中的文件名。

第二步是下載所有文件:

    with concurrent.futures.ThreadPoolExecutor(max_workers=MAX_THREADS) as executor:
        executor.map(lambda s3key:  bucket_obj.download_file(s3key, local_filepath, Config=CUSTOM_CONFIG),                         
                    filtered_s3keys)

為簡單起見,我跳過了這一事實,即代碼為每個下載的文件生成一個 local_filepath,因此它是您真正想要的文件以及您想要它的位置。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM