通过 Python 代码覆盖 Google Cloud Storage 存储桶中的单个文件

Dav*_*osa 5 python google-cloud-storage google-compute-engine google-cloud-platform

logs.txtCompute Engine VM Instance 的某个位置有一个文件。我想定期在Google Cloud Storage 存储桶中备份(即覆盖)。由于是在 Python 脚本内进行一些预处理的结果,我还想使用该脚本将该文件上传/复制到 Google Cloud Storage 存储桶中(因此,不能将视为一个选项)。Compute Engine 虚拟机实例和 Cloud Storage 存储桶都位于同一个 GCP 项目中,因此“它们可以看到彼此”。基于此示例代码,我现在正在尝试的内容如下所示:logs.txtlogs.txtcp

from google.cloud import storage

bucket_name = "my-bucket"
destination_blob_name = "logs.txt"
source_file_name = "logs.txt"  # accessible from this script

storage_client = storage.Client()
bucket = storage_client.bucket(bucket_name)
blob = bucket.blob(destination_blob_name)

generation_match_precondition = 0
blob.upload_from_filename(source_file_name, if_generation_match=generation_match_precondition)

print(f"File {source_file_name} uploaded to {destination_blob_name}.")
Run Code Online (Sandbox Code Playgroud)

如果gs://my-bucket/logs.txt不存在,脚本可以正常工作,但是如果我尝试覆盖,则会出现以下错误:

Traceback (most recent call last):
  File "/usr/local/lib/python3.8/dist-packages/google/cloud/storage/blob.py", line 2571, in upload_from_file
    created_json = self._do_upload(
  File "/usr/local/lib/python3.8/dist-packages/google/cloud/storage/blob.py", line 2372, in _do_upload
    response = self._do_multipart_upload(
  File "/usr/local/lib/python3.8/dist-packages/google/cloud/storage/blob.py", line 1907, in _do_multipart_upload
    response = upload.transmit(
  File "/usr/local/lib/python3.8/dist-packages/google/resumable_media/requests/upload.py", line 153, in transmit
    return _request_helpers.wait_and_retry(
  File "/usr/local/lib/python3.8/dist-packages/google/resumable_media/requests/_request_helpers.py", line 147, in wait_and_retry
    response = func()
  File "/usr/local/lib/python3.8/dist-packages/google/resumable_media/requests/upload.py", line 149, in retriable_request
    self._process_response(result)
  File "/usr/local/lib/python3.8/dist-packages/google/resumable_media/_upload.py", line 114, in _process_response
    _helpers.require_status_code(response, (http.client.OK,), self._get_status_code)
  File "/usr/local/lib/python3.8/dist-packages/google/resumable_media/_helpers.py", line 105, in require_status_code
    raise common.InvalidResponse(
google.resumable_media.common.InvalidResponse: ('Request failed with status code', 412, 'Expected one of', <HTTPStatus.OK: 200>)

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/my_folder/upload_to_gcs.py", line 76, in <module>
    blob.upload_from_filename(source_file_name, if_generation_match=generation_match_precondition)
  File "/usr/local/lib/python3.8/dist-packages/google/cloud/storage/blob.py", line 2712, in upload_from_filename
    self.upload_from_file(
  File "/usr/local/lib/python3.8/dist-packages/google/cloud/storage/blob.py", line 2588, in upload_from_file
    _raise_from_invalid_response(exc)
  File "/usr/local/lib/python3.8/dist-packages/google/cloud/storage/blob.py", line 4455, in _raise_from_invalid_response
    raise exceptions.from_http_status(response.status_code, message, response=response)
google.api_core.exceptions.PreconditionFailed: 412 POST https://storage.googleapis.com/upload/storage/v1/b/production-onementor-dt-data/o?uploadType=multipart&ifGenerationMatch=0: {
  "error": {
    "code": 412,
    "message": "At least one of the pre-conditions you specified did not hold.",
    "errors": [
      {
        "message": "At least one of the pre-conditions you specified did not hold.",
        "domain": "global",
        "reason": "conditionNotMet",
        "locationType": "header",
        "location": "If-Match"
      }
    ]
  }
}
: ('Request failed with status code', 412, 'Expected one of', <HTTPStatus.OK: 200>)
Run Code Online (Sandbox Code Playgroud)

我已经检查了文档upload_from_filename,但似乎没有“启用覆盖”的标志。

如何使用Python语言正确覆盖Google云存储桶中现有的文件?

Ema*_*l P 7

这是因为if_ Generation_match

作为一种特殊情况,仅当不存在 blob 的实时版本时,传递 0 作为 if_ Generation_match 的值才会使操作成功。

这就是返回消息“至少您指定的先决条件之一不成立”的含义。

你应该忽略None或完全忽略这个论点。

  • 更新:就我而言,为了强制覆盖,出于某种原因,我必须将 `if_ Generation_match` 和 `if_meta Generation_match` 设置为 None 。 (2认同)