json 将文件从S3存储桶复制到另一个存储桶的功能会添加额外的文件

63lcw9qa  于 2023-05-30  发布在  其他
关注(0)|答案(1)|浏览(253)

我有一个S3存储桶“data”,其中包含一个目录“20230225”,其中包含JSON和视频文件。在'20230225'中,我创建了一个子目录'metadata',我想在其中移动JSON文件,以便将所有JSON和视频文件放在单独的目录中。
我写了一个函数将JSON文件复制到另一个目录,它似乎可以处理一小部分数据。然而,当我在'20230225'中的所有JSON文件上运行该函数时,它所花费的时间比我预期的要长得多。我中断了函数的执行,当我计算目标目录中的文件时,a有比应该在那里的更多的json文件。
下面是函数代码。有什么东西可以添加一些额外的文件吗?
我想这可能是因为源文件夹也将是所有的子目录,而唯一的源文件夹的子目录实际上是目标文件夹,所以可能函数在试图从它已经复制的目标文件夹复制文件时陷入了循环。
然而,即使是这种情况下,它不应该只是覆盖这些文件,而不是添加额外的文件?

def copy_json_files(s3_bucket: str, source_folder: str, dest_folder: str):
    """
    Parameters:
    - s3_bucket (str): The name of the S3 bucket.
    - source_folder (str): The name of the source folder.
    - dest_folder (str): The name of the destination folder.
    
    Returns:
    - int: The number of files copied.
    """

    s3 = boto3.resource('s3')
    src_bucket = s3.Bucket(s3_bucket)

    # Create destination prefix
    dest_prefix = dest_folder.strip('/') + '/' if dest_folder else ''

    # Configure S3 transfer manager
    botocore_config = botocore.config.Config(max_pool_connections=200)
    s3client = boto3.client('s3', config=botocore_config)
    transfer_config = s3transfer.TransferConfig(use_threads=True, max_concurrency=140)

    # Create S3 transfer manager
    s3t = s3transfer.create_transfer_manager(s3client, transfer_config)

    copied_files = 0
    
    for obj in src_bucket.objects.filter(Prefix=source_folder):
        # Exclude objects in subdirectories of source folder
        if '/' in obj.key[len(source_folder):]:
            continue
            
        # Exclude objects already in the destination folder
        if obj.key.startswith(dest_prefix):
            continue
            
        if obj.key.endswith('.json'):
            # Form destination key by replacing source folder name with destination folder name
            dest_key = obj.key.replace(source_folder, dest_prefix, 1)

            copy_source = {
                'Bucket': s3_bucket,
                'Key': obj.key
            }

            s3t.copy(
                copy_source=copy_source,
                bucket=s3_bucket,
                key=dest_key
            )
            
            copied_files += 1

    # Close transfer manager
    s3t.shutdown()

    return copied_files

我用来检查文件数量的函数是:

def count_files(s3_bucket, s3_dir):
    
    s3_resource = boto3.resource('s3')
    bucket = s3_resource.Bucket(s3_bucket)

    count = 0
    for obj in bucket.objects.filter(Prefix=s3_dir):
        count += 1
    
    return count
1bqhqjot

1bqhqjot1#

子文件夹中的对象将包括在对象列表中。
例如,如果源代码有一个对象,并且您的代码正在运行,则它会将该对象复制到子目录中。下一次运行时,它会将两个对象复制到子文件夹,因为src_bucket.objects.filter(Prefix=source_folder)将 * 包括 * 所有子文件夹。
如果您只想复制源文件夹“顶部”中的对象,则需要:

将目标移动到其他位置(即不作为源的子文件夹), 或 *
*添加一些逻辑,检查要复制的对象是否 * 不在 * 子文件夹中-例如获取最后一个/之前的键中的所有内容,并将其与源文件夹的名称进行比较。

相关问题