将文件上传到 GCS,如果存在则跳过 python

Upload files to GCS, skip if existed using python

我有一个名为 my-gcs 的 GCS,其子文件夹不一致,例如;

parent-path/path1/path2/*
parent-path/path3/path4/path5/*
parent-path/path6/*

文件可以是 parquet/csv 或其他。

这是我将整个文件夹从本地复制到 GCS 的功能:

def upload_local_directory_to_gcs(src_path, dest_path, data_backup, file_name):
    """
    Upload the whole directory to GCS
    """
    logger.debug("Uploading directory...")

    storage_client = storage.Client.from_service_account_json(key_path)
    bucket = storage_client.get_bucket(GCS_BUCKET)

    if os.path.isfile(src_path):
        blob = bucket.blob(os.path.join(dest_path, os.path.basename(src_path)))
        blob.upload_from_filename(src_path)
        return

    for item in glob.glob(src_path + '/*'):

        file_exist = check_file_exist(data_backup, file_name)

        if os.path.isfile(item):
            print(item)

            if file_exist is False:
                blob = bucket.blob(os.path.join(dest_path, os.path.basename(item)),
                                   chunk_size=10485760)
                blob.upload_from_filename(item)
            else:
                logger.warning("Skipping upload. File already existed")

        else:
            if file_exist is False:
                upload_local_directory_to_gcs(item, os.path.join(dest_path, os.path.basename(item)),
                                            data_backup, file_name)
            else:
                logger.warning("Skipping upload. File already existed")

这是检查目录和子目录中是否存在特定文件的函数:

def check_file_exist(dataset, file_name):
    """
    Check if files existed
    """
    storage_client = storage.Client.from_service_account_json(key_path)
    bucket = storage_client.bucket(GCS_BUCKET)

    logger.debug("Checking if file already existed in GCS to skip upload...")

    blobs = bucket.list_blobs(prefix=f'parent-path{dataset}/')
    check_files = [blob.name for blob in blobs if file_name in blob.name] #  if '.' in blob.name

    return bool(len(check_files))

但是代码 运行 不正确。假设此路径 parent-path/path1/path2/* 已经有一个名为 first_file.csv 的文件。它将跳过上传此路径中的现有文件。直到遇到一个不存在的文件,它会上传该文件并覆盖所有目录的其他文件。

我期望它只上传尚不存在的特定文件,而不会覆盖其他文件。

我尽力解释了...请帮忙。

如果您查看 documentation,您可以在 blob

的名称 属性 上看到

The name of the blob. This corresponds to the unique path of the object in the bucket.

这意味着该值不仅是文件名,而且是完全限定路径+名称path/to/file.csv

如果循环,请检查文件名(例如 file.csv)是否包含在 blob 路径中。考虑这种情况

path/to/file.csv
path/to/to/file.csv

如果您测试 file.csv 存在,则两个 blob 都将 return 为真。

要解决您的问题,您需要

  • 要么比较target_path+file_name和blob.name
  • 的严格相等
  • 或者在您的“if”中包含一个附加条件,以包含要检查的存储桶路径以及文件名。