Как отправить / скопировать / загрузить файл из AWS S3 в Google GCS с помощью Python

#python #amazon-s3 #google-cloud-storage #boto3 #gcloud

#python #amazon-s3 #google-облачное хранилище #boto3 #gcloud

Вопрос:

Я ищу pythonic способ копирования файла из AWS S3 в GCS.

Я не хочу открывать / читать файл, а затем использовать метод blob.upload_from_string(). Я хочу передать его «как есть».

Я не могу использовать ‘gsutils’. Объем библиотек, с которыми я работаю, — gcloud, boto3 (также экспериментировал с s3fs).

Вот простой пример (который, похоже, работает) с использованием метода blob.upload_from_string(), которого я пытаюсь избежать, потому что я не хочу открывать / читать файл. Я не могу заставить его работать с помощью метода blob.upload_from_file(), потому что GCS api требует доступного, читаемого, файлоподобного объекта, который я не могу предоставить должным образом.

Чего мне не хватает? Предложения?

 import boto3
from gcloud import storage
from oauth2client.service_account import ServiceAccountCredentials

GSC_Token_File = 'path/to/GSC_token'

s3 = boto3.client('s3', region_name='MyRegion') # im running from AWS Lambda, no authentication required

gcs_credentials = ServiceAccountCredentials.from_json_keyfile_dict(GSC_Token_File)
gcs_storage_client = storage.Client(credentials=gcs_credentials, project='MyGCP_project')
gcs_bucket = gcs_storage_client.get_bucket('MyGCS_bucket')

s3_file_to_load = str(s3.get_object(Bucket='MyS3_bucket', Key='path/to/file_to_copy.txt')['Body'].read().decode('utf-8'))
blob = gcs_bucket.blob('file_to_copy.txt')

blob.upload_from_string(s3_file_to_load)

  

Ответ №1:

Итак, я еще немного покопался и наткнулся на эту статью, которая в конечном итоге привела меня к этому решению. По-видимому, API GCS можно вызвать с помощью AWS boto3 SDK.

Пожалуйста, обратите внимание на обязательное условие ключа HMAC, которое можно легко создать с помощью этих инструкций.

 import boto3

# im using GCP Service Account so my HMAC was created accordingly. 
# HMAC for User Account can be created just as well

service_Access_key = 'YourAccessKey'
service_Secret = 'YourSecretKey'

# Reminder: I am copying from S3 to GCS
s3_client = boto3.client('s3', region_name='MyRegion')
gcs_client  =boto3.client(
        "s3", # !just like that
        region_name="auto",
        endpoint_url="https://storage.googleapis.com",
        aws_access_key_id=service_Access_key,
        aws_secret_access_key=service_Secret,
    )


file_to_transfer = s3_client.get_object(Bucket='MyS3_bucket', Key='path/to/file_to_copy.txt')
gcs_client.upload_fileobj(file_to_transfer['Body'], 'MyGCS_bucket', 'file_to_copy.txt')


  

Ответ №2:

Я понимаю, что вы пытаетесь переместить файлы из S3 в CGS, используя Python в функции AWS Lambda. Есть одна вещь, которую я хотел бы прояснить из заявления «Я не хочу открывать / читать файл», которая заключается в том, что когда файл загружается с S3, вы действительно читаете его и записываете куда-то, будь то в строку в памяти или во временный файл. В этом смысле на самом деле не имеет значения, какой из blob.upload_from_file() or blob.upload_from_string() используется, поскольку они эквивалентны; первый будет считываться из файла, а второй — нет, потому что данные уже считаны в памяти. Поэтому я предлагаю сохранить код таким, какой он есть, я не вижу пользы в его изменении.

В любом случае должен быть возможен подход к файлу, делающий что-то вроде приведенных ниже строк (непроверенный, у меня нет S3 для проверки):

 # From S3 boto docs: https://boto3.amazonaws.com/v1/documentation/api/latest/guide/s3-example-download-file.html
s3.download_file('BUCKET_NAME', 'OBJECT_NAME', 'FILE_NAME')
blob.upload_from_file('FILE_NAME')
  

Наконец, стоит упомянуть инструмент переноса хранилища, который предназначен для перемещения огромных объемов данных из S3 в GCS. Если это похоже на ваш вариант использования, вы можете взглянуть на примеры кода для Python.