বোটো 3 ব্যবহার করে কোনও ফাইলের মধ্যে S3 অবজেক্টটি কীভাবে সংরক্ষণ করবেন


132

আমি এডাব্লুএসের জন্য নতুন বোটো 3 ক্লায়েন্টের সাথে একটি "হ্যালো ওয়ার্ল্ড" করার চেষ্টা করছি ।

আমার কাছে থাকা ইউস-কেসটি মোটামুটি সহজ: এস 3 থেকে অবজেক্ট পান এবং এটি ফাইলটিতে সংরক্ষণ করুন।

বোটো 2.XI এ এটি করবে:

import boto
key = boto.connect_s3().get_bucket('foo').get_key('foo')
key.get_contents_to_filename('/tmp/foo')

বোটো 3 এ। আমি একই জিনিসটি করার কোনও পরিষ্কার উপায় খুঁজে পাচ্ছি না, তাই আমি নিজে "স্ট্রিমিং" অবজেক্টটি নিয়ে পুনরুক্তি করছি:

import boto3
key = boto3.resource('s3').Object('fooo', 'docker/my-image.tar.gz').get()
with open('/tmp/my-image.tar.gz', 'w') as f:
    chunk = key['Body'].read(1024*8)
    while chunk:
        f.write(chunk)
        chunk = key['Body'].read(1024*8)

অথবা

import boto3
key = boto3.resource('s3').Object('fooo', 'docker/my-image.tar.gz').get()
with open('/tmp/my-image.tar.gz', 'w') as f:
    for chunk in iter(lambda: key['Body'].read(4096), b''):
        f.write(chunk)

এবং এটি সূক্ষ্ম কাজ করে। আমি ভাবছিলাম যে কোনও "নেটিভ" বোটো 3 ফাংশন আছে যা একই কাজটি করবে?

উত্তর:


216

সম্প্রতি বোটো 3 এ একটি কাস্টমাইজেশন রয়েছে যা এটি (অন্যান্য জিনিসের মধ্যে) সাথে সহায়তা করে। এটি বর্তমানে নিম্ন-স্তরের এস 3 ক্লায়েন্টের সামনে প্রকাশ করা হয়েছে এবং এটি ব্যবহার করা যেতে পারে:

s3_client = boto3.client('s3')
open('hello.txt').write('Hello, world!')

# Upload the file to S3
s3_client.upload_file('hello.txt', 'MyBucket', 'hello-remote.txt')

# Download the file from S3
s3_client.download_file('MyBucket', 'hello-remote.txt', 'hello2.txt')
print(open('hello2.txt').read())

এই ফাংশনগুলি স্বয়ংক্রিয়ভাবে পঠন / লেখার ফাইলগুলি হ্যান্ডেল করবে পাশাপাশি বড় ফাইলগুলির সমান্তরালে একাধিক আপলোডগুলি করবে।

নোট করুন যে s3_client.download_fileকোনও ডিরেক্টরি তৈরি করবে না। এটি হিসাবে তৈরি করা যেতে পারে pathlib.Path('/path/to/file.txt').parent.mkdir(parents=True, exist_ok=True)


1
@ ড্যানিয়েল: আপনার উত্তরের জন্য ধন্যবাদ বোটো 3-তে মাল্টিপার্ট আপলোড ব্যবহার করে ফাইল আপলোড করতে চাইলে আপনি কি উত্তরটি দিতে পারেন
রাহুল কেপি

1
@ রাহুলকুমারপ্যাটল upload_fileপদ্ধতিটি বড় বড় ফাইলগুলির জন্য স্বয়ংক্রিয়ভাবে মাল্টিপার্ট আপলোডগুলি ব্যবহার করবে।
ড্যানিয়েল

4
আপনি এই পদ্ধতির ব্যবহার করে শংসাপত্রগুলি কীভাবে পাস করবেন?
JHowIX

1
@ জেউইআইএক্স আপনি বিশ্বব্যাপী শংসাপত্রগুলি কনফিগার করতে পারেন (যেমন দেখুন বোটো3.ড্রেডহেডসস.আর.ইন / স্লেট / গুইড/… ) অথবা ক্লায়েন্ট তৈরি করার সময় আপনি সেগুলি পাস করতে পারেন। উপলভ্য বিকল্পগুলির জন্য আরও তথ্যের জন্য boto3.readthedocs.org/en/latest/references/core/… দেখুন !
ড্যানিয়েল

2
@ ভ্লাদনিকিপুরফ "উত্স থেকে গন্তব্যে আপলোড করুন" "উত্স থেকে গন্তব্যে ডাউনলোড করুন"
জেকেদেব

59

বোটো 3 এর ক্লায়েন্টের চেয়ে ভাল ইন্টারফেস রয়েছে:

resource = boto3.resource('s3')
my_bucket = resource.Bucket('MyBucket')
my_bucket.download_file(key, local_filename)

এটি স্বয়ংক্রিয়ভাবে clientগৃহীত উত্তরের চেয়ে মারাত্মকভাবে ভাল নয় (যদিও ডকস বলে যে এটি আপলোড এবং ব্যর্থতায় ডাউনলোডগুলি পুনরায় চেষ্টা করার চেয়ে আরও ভাল কাজ করে) তবে মনে করা হয় যে সংস্থানগুলি সাধারণত আরও অর্গানমিক (উদাহরণস্বরূপ, এস 3 বালতি এবং বস্তুর সংস্থানসমূহ) ক্লায়েন্ট পদ্ধতিগুলির তুলনায় খুব সুন্দর) এটি আপনাকে নিচে নামিয়ে ছাড়াই সংস্থান লেয়ারে থাকতে দেয়।

Resources সাধারণত ক্লায়েন্ট হিসাবে একইভাবে তৈরি করা যেতে পারে, এবং তারা সমস্ত বা বেশিরভাগ একই যুক্তি গ্রহণ করে এবং কেবল তাদের অভ্যন্তরীণ ক্লায়েন্টদের কাছে ফরোয়ার্ড করে।


1
দুর্দান্ত উদাহরণ, এবং যেহেতু মূল প্রশ্নটি কোনও বস্তু সংরক্ষণের বিষয়ে জিজ্ঞাসা করে তা যুক্ত করতে এখানে প্রাসঙ্গিক পদ্ধতিটি my_bucket.upload_file()(বা আপনার my_bucket.upload_fileobj()যদি বাইটসআইও অবজেক্ট থাকে)।
এসএমএক্স

দস্তাবেজগুলি ঠিক কোথায় বলবে যা আবার resourceচেষ্টা করার চেয়ে আরও ভাল কাজ করে? আমি এরকম কোনও ইঙ্গিত পাইনি।
একিউম্যানাস

42

আপনারা যারা এই set_contents_from_stringজাতীয় বোটো 2 পদ্ধতিগুলি অনুকরণ করতে চান, আপনি চেষ্টা করতে পারেন

import boto3
from cStringIO import StringIO

s3c = boto3.client('s3')
contents = 'My string to save to S3 object'
target_bucket = 'hello-world.by.vor'
target_file = 'data/hello.txt'
fake_handle = StringIO(contents)

# notice if you do fake_handle.read() it reads like a file handle
s3c.put_object(Bucket=target_bucket, Key=target_file, Body=fake_handle.read())

পাইথন 3 এর জন্য:

পাইথন 3 এ স্ট্রিংআইও এবং সিস্ট্রিংআইও উভয়ই চলে গেছেStringIOআমদানি যেমন ব্যবহার করুন :

from io import StringIO

উভয় সংস্করণ সমর্থন করতে:

try:
   from StringIO import StringIO
except ImportError:
   from io import StringIO

15
এটাই উত্তর। এখানে প্রশ্নটি রয়েছে: "আপনি বোটো 3 ব্যবহার করে কোনও স্ট্রিং S3 অবজেক্টে কীভাবে সংরক্ষণ করবেন?"
jkdev

পাইথন 3 এর জন্য আমাকে আমদানি io ব্যবহার করতে হয়েছিল; নকল_হ্যান্ডল ই = আইও স্ট্রিংআইও (সামগ্রী)
ফেলিক্স

16
# Preface: File is json with contents: {'name': 'Android', 'status': 'ERROR'}

import boto3
import io

s3 = boto3.resource('s3')

obj = s3.Object('my-bucket', 'key-to-file.json')
data = io.BytesIO()
obj.download_fileobj(data)

# object is now a bytes string, Converting it to a dict:
new_dict = json.loads(data.getvalue().decode("utf-8"))

print(new_dict['status']) 
# Should print "Error"

14
আপনার কোডটিতে কখনও আপনার AWS_ACCESS_KEY_ID বা আপনার AWS_SECRET_ACCESS_KEY রাখবেন না। এগুলি awscli aws configureকমান্ডের সাহায্যে সংজ্ঞায়িত করা উচিত এবং সেগুলি স্বয়ংক্রিয়ভাবে খুঁজে পাওয়া যাবে botocore
মাইলস এরিকসন

3

আপনি যখন ডিফল্টর চেয়ে আলাদা কনফিগারেশন সহ কোনও ফাইল পড়তে চান, তখন mpu.aws.s3_download(s3path, destination)সরাসরি বা অনুলিপি-কোডযুক্ত কোডটি ব্যবহার করতে দ্বিধা বোধ করবেন :

def s3_download(source, destination,
                exists_strategy='raise',
                profile_name=None):
    """
    Copy a file from an S3 source to a local destination.

    Parameters
    ----------
    source : str
        Path starting with s3://, e.g. 's3://bucket-name/key/foo.bar'
    destination : str
    exists_strategy : {'raise', 'replace', 'abort'}
        What is done when the destination already exists?
    profile_name : str, optional
        AWS profile

    Raises
    ------
    botocore.exceptions.NoCredentialsError
        Botocore is not able to find your credentials. Either specify
        profile_name or add the environment variables AWS_ACCESS_KEY_ID,
        AWS_SECRET_ACCESS_KEY and AWS_SESSION_TOKEN.
        See https://boto3.readthedocs.io/en/latest/guide/configuration.html
    """
    exists_strategies = ['raise', 'replace', 'abort']
    if exists_strategy not in exists_strategies:
        raise ValueError('exists_strategy \'{}\' is not in {}'
                         .format(exists_strategy, exists_strategies))
    session = boto3.Session(profile_name=profile_name)
    s3 = session.resource('s3')
    bucket_name, key = _s3_path_split(source)
    if os.path.isfile(destination):
        if exists_strategy is 'raise':
            raise RuntimeError('File \'{}\' already exists.'
                               .format(destination))
        elif exists_strategy is 'abort':
            return
    s3.Bucket(bucket_name).download_file(key, destination)

from collections import namedtuple

S3Path = namedtuple("S3Path", ["bucket_name", "key"])


def _s3_path_split(s3_path):
    """
    Split an S3 path into bucket and key.

    Parameters
    ----------
    s3_path : str

    Returns
    -------
    splitted : (str, str)
        (bucket, key)

    Examples
    --------
    >>> _s3_path_split('s3://my-bucket/foo/bar.jpg')
    S3Path(bucket_name='my-bucket', key='foo/bar.jpg')
    """
    if not s3_path.startswith("s3://"):
        raise ValueError(
            "s3_path is expected to start with 's3://', " "but was {}"
            .format(s3_path)
        )
    bucket_key = s3_path[len("s3://"):]
    bucket_name, key = bucket_key.split("/", 1)
    return S3Path(bucket_name, key)

কাজ করে না। NameError: name '_s3_path_split' is not defined
ডেভ লিউ

@ ডেভলিউ ইঙ্গিতটির জন্য আপনাকে ধন্যবাদ; আমি কোড সামঞ্জস্য করেছি প্যাকেজটির আগে কাজ করা উচিত ছিল।
মার্টিন থোমা

1

দ্রষ্টব্য: আমি ধরে নিচ্ছি আপনি পৃথকভাবে প্রমাণীকরণ কনফিগার করেছেন। কোডের নীচে এস 3 বালতি থেকে একক অবজেক্টটি ডাউনলোড করতে হবে।

import boto3

#initiate s3 client 
s3 = boto3.resource('s3')

#Download object to the file    
s3.Bucket('mybucket').download_file('hello.txt', '/tmp/hello.txt')
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.