boto3を使用してファイルまたはデータをS3オブジェクトに書き込む方法


103

boto 2では、次のメソッドを使用してS3オブジェクトに書き込むことができます。

boto 3に相当するものはありますか?S3に格納されているオブジェクトにデータを保存するboto3メソッドとは何ですか?

回答:


210

boto 3では、「Key.set_contents_from_」メソッドは、

例えば:

import boto3

some_binary_data = b'Here we have some data'
more_binary_data = b'Here we have some more data'

# Method 1: Object.put()
s3 = boto3.resource('s3')
object = s3.Object('my_bucket_name', 'my/key/including/filename.txt')
object.put(Body=some_binary_data)

# Method 2: Client.put_object()
client = boto3.client('s3')
client.put_object(Body=more_binary_data, Bucket='my_bucket_name', Key='my/key/including/anotherfilename.txt')

または、公式ドキュメントのboto 2とboto 3の比較で説明されているように、バイナリデータはファイルの読み取りから取得できます。

データの保存

ファイル、ストリーム、または文字列からのデータの保存は簡単です。

# Boto 2.x
from boto.s3.key import Key
key = Key('hello.txt')
key.set_contents_from_file('/tmp/hello.txt')

# Boto 3
s3.Object('mybucket', 'hello.txt').put(Body=open('/tmp/hello.txt', 'rb'))

botocore.exceptions.NoCredentialsError:資格情報が見つからないため、これを修正する方法
ディーパックマーシー

2
@deepakmurthyエラーが発生する理由がわかりません... 新しいStack Overflowの質問をして、問題の詳細を提供する必要があります
jkdev

1
試してみるs3.Object().put()と、ゼロのオブジェクトになってしまいますcontent-length。私にとってput()は文字列データのみを受け入れますput(str(binarydata)) が、なんらかのエンコードの問題があるようです。元のデータの約3倍のサイズのオブジェクトができてしまい、役に立たなくなります。
user1129682 2018

@ user1129682なぜかはわかりません。新しい質問をして詳細を教えてください。
jkdev 2018

あなたができれば@jkdevそれは素晴らしいことだ見てみましょう
user1129682

48

boto3には、ファイルを直接アップロードする方法もあります。

s3.Bucket('bucketname').upload_file('/local/file/here.txt','folder/sub/path/to/s3key')

http://boto3.readthedocs.io/en/latest/reference/services/s3.html#S3.Bucket.upload_file


5
これは良いことですが、現在メモリ内にあるデータを保存することはできません。
リード

3
@Reid:インメモリファイルの場合は、s3.Bucket(...).upload_fileobj()代わりにメソッドを使用できます。
svohara

36

S3でファイルに書き込む前に、内容をバイナリに変換する必要がなくなりました。次の例では、S3バケットに文字列の内容を含む新しいテキストファイル(newfile.txtという名前)を作成します。

import boto3

s3 = boto3.resource(
    's3',
    region_name='us-east-1',
    aws_access_key_id=KEY_ID,
    aws_secret_access_key=ACCESS_KEY
)
content="String content to write to a new S3 file"
s3.Object('my-bucket-name', 'newfile.txt').put(Body=content)

私の「プット」アクションがアクセスできないとは思いません。このバケットを作成し、正規IDをアクセスリストの下に配置しました。
陳林

prefixこの場合、どのようにを与えますか?つまり、ファイルを保存したい場合はどうなりますmy-bucket-name/subfolder/か?
kev

3
@kevでは、「newfile.txt」の代わりに「subfolder / newfile.txt」というファイル名を指定できます
Madhava Carrillo

「S3でファイルに書き込む前に内容をバイナリに変換する必要がなくなりました。」について、これはどこかに文書化されていますか?私はboto3.amazonaws.com/v1/documentation/api/latest/reference/…を見ていて、バイトのみを受け入れると思っていました。「シーク可能なファイルのようなオブジェクト」を正確に構成するものはわかりませんが、文字列が含まれているとは思いませんでした。
エマ

これを、大きなマルチパートファイルのアップロード用のdownload_fileobj()と比較する必要があるかもしれません。アップロードメソッドにはシーク可能なファイルオブジェクトが必要ですが、put()を使用すると、バケット内のファイルに文字列を直接書き込むことができます。これは、ラムダ関数がファイルを動的に作成してS3バケットに書き込むのに便利です。
フランケ

28

以下は、s3からJSONを読み取るための素晴らしいトリックです。

import json, boto3
s3 = boto3.resource("s3").Bucket("bucket")
json.load_s3 = lambda f: json.load(s3.Object(key=f).get()["Body"])
json.dump_s3 = lambda obj, f: s3.Object(key=f).put(Body=json.dumps(obj))

今、あなたは使用することができますjson.load_s3し、json.dump_s3同じAPIを持つloaddump

data = {"test":0}
json.dump_s3(data, "key") # saves json to s3://bucket/key
data = json.load_s3("key") # read json from s3://bucket/key

2
優れた。これを機能させるために、次のビットを追加しました...["Body"].read().decode('utf-8')
sedeh

いい案。とにかく、ネーミングを改善するためのスペースを提供します。
Jan Vlcinsky

この素晴らしいアイデアの書き換えの提案:gist.github.com/vlcinsky/bbeda4321208aa98745afc29b58e90ac
Jan Vlcinsky

12

特定のS3バケットとサブフォルダーにオンザフライでファイルをアップロードするために使用する、より簡潔で簡潔なバージョン-

import boto3

BUCKET_NAME = 'sample_bucket_name'
PREFIX = 'sub-folder/'

s3 = boto3.resource('s3')

# Creating an empty file called "_DONE" and putting it in the S3 bucket
s3.Object(BUCKET_NAME, PREFIX + '_DONE').put(Body="")

:AWSの認証情報(aws_access_key_idaws_secret_access_key)は、必ず別のファイルに入れてください。たとえば、~/.aws/credentials


Windowsではサポートされないため、AWS認証情報ファイルのWindows対応の場所はどこですか~
Hamman Samuel

1
@HammanSamuelは次のように保存できますC:\Users\username\.aws\credentials
kev

1

バックエンドとして使用するsmart-openについて言及する価値がありboto3ます。

smart-openドロップでPythonのための代替であるopenからファイルを開くことができるs3、などftphttpおよび他の多くのプロトコルが。

例えば

from smart_open import open
import json
with open("s3://your_bucket/your_key.json", 'r') as f:
    data = json.load(f)

aws資格情報はboto3資格情報、通常は~/.aws/dir 内のファイルまたは環境変数を介してロードされます。


1
この応答は参考情報ですが、元の質問への回答には従いません。つまり、特定のbotoメソッドに相当するboto3とは何ですか。
robinhood91

1
スマートオープンはboto3を使用
Uri Goren

1

以下のコードを使用して、たとえば2019年にS3にイメージを書き込むことができます。S3に接続できるようにするにはpip install awscli、コマンドを使用してAWS CLIをインストールし、コマンドを使用していくつかの認証情報を入力する必要がありますaws configure

import urllib3
import uuid
from pathlib import Path
from io import BytesIO
from errors import custom_exceptions as cex

BUCKET_NAME = "xxx.yyy.zzz"
POSTERS_BASE_PATH = "assets/wallcontent"
CLOUDFRONT_BASE_URL = "https://xxx.cloudfront.net/"


class S3(object):
    def __init__(self):
        self.client = boto3.client('s3')
        self.bucket_name = BUCKET_NAME
        self.posters_base_path = POSTERS_BASE_PATH

    def __download_image(self, url):
        manager = urllib3.PoolManager()
        try:
            res = manager.request('GET', url)
        except Exception:
            print("Could not download the image from URL: ", url)
            raise cex.ImageDownloadFailed
        return BytesIO(res.data)  # any file-like object that implements read()

    def upload_image(self, url):
        try:
            image_file = self.__download_image(url)
        except cex.ImageDownloadFailed:
            raise cex.ImageUploadFailed

        extension = Path(url).suffix
        id = uuid.uuid1().hex + extension
        final_path = self.posters_base_path + "/" + id
        try:
            self.client.upload_fileobj(image_file,
                                       self.bucket_name,
                                       final_path
                                       )
        except Exception:
            print("Image Upload Error for URL: ", url)
            raise cex.ImageUploadFailed

        return CLOUDFRONT_BASE_URL + id
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.