Boto3 का उपयोग करके किसी S3 ऑब्जेक्ट में फ़ाइल या डेटा कैसे लिखें


105

बोटो 2 में, आप इन विधियों का उपयोग करके S3 ऑब्जेक्ट को लिख सकते हैं:

वहाँ एक बोटो 3 बराबर है? S3 पर संग्रहीत किसी वस्तु को डेटा बचाने के लिए boto3 विधि क्या है?

जवाबों:


212

बोटो 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')

वैकल्पिक रूप से, द्विआधारी डेटा एक फ़ाइल को पढ़ने से आ सकता है, जैसा कि आधिकारिक डॉक्स में बोटो 2 और बोटो 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.exception.NoCredentialsError: क्रेडेंशियल्स का पता लगाने में असमर्थ इसे कैसे ठीक करें?
गहरा मूर्ति

2
@deepakmurthy मुझे यकीन नहीं है कि आपको वह त्रुटि क्यों मिल रही है ... आपको एक नया स्टैक ओवरफ्लो प्रश्न पूछने और मुद्दे के बारे में अधिक जानकारी प्रदान करने की आवश्यकता होगी ।
jkdev

1
जब मैं कोशिश करता s3.Object().put()हूं तो मैं शून्य के साथ एक वस्तु के साथ समाप्त होता हूं content-length। मेरे लिए put()केवल स्ट्रिंग डेटा स्वीकार करता है, लेकिन put(str(binarydata)) लगता है कि एन्कोडिंग मुद्दों के कुछ प्रकार हैं। मैं मूल डेटा के आकार के लगभग 3 गुना अधिक वस्तु के साथ समाप्त होता हूं, जिससे यह मेरे लिए बेकार हो जाता है।
user1129682

@ user1129682 मुझे यकीन नहीं है कि ऐसा क्यों है। क्या आप एक नया प्रश्न पूछ सकते हैं और अधिक विवरण प्रदान कर सकते हैं ?
जकदेव

@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
@ रीड: इन-मेमोरी फ़ाइलों के लिए आप s3.Bucket(...).upload_fileobj()इसके बजाय विधि का उपयोग कर सकते हैं ।
सुवहरा

37

आपको अब 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)

पता नहीं मेरे 'डाल' कार्रवाई का कोई उपयोग नहीं है। मैंने इस बकेट को बनाया और एक्सेस सूची के तहत अपनी विहित आईडी डाल दी।
चेन लिन

prefixइस मामले में आप कैसे देते हैं ? मतलब, अगर आप फाइल को स्टोर करना चाहते हैं तो क्या होगा my-bucket-name/subfolder/?
केव

3
@kev आप निर्दिष्ट कर सकते हैं कि फ़ाइल नाम 'सबफ़ोल्डर / newfile.txt' के स्थान पर 'newfile.txt' के बजाय
माधव कारिलो

"S3 में फ़ाइल में लिखने से पहले आपको सामग्री को बाइनरी में बदलना नहीं होगा।", क्या यह कहीं दस्तावेज है? मैं boto3.amazonaws.com/v1/documentation/api/latest/reference/… को देख रहा था , और सोचा कि यह केवल बाइट्स को स्वीकार करेगा। मुझे यकीन नहीं है कि वास्तव में एक "खोज योग्य फ़ाइल जैसी वस्तु" क्या है, लेकिन यह नहीं सोचा कि इसमें तार शामिल हैं।
एम्मा

मैं इसे डाउनलोड_फाइलोबज () के साथ तुलना कर सकता हूं जो कि बड़े मल्टीपार्ट फाइल अपलोड के लिए है। अपलोड के तरीकों के लिए खोज योग्य फ़ाइल ऑब्जेक्ट्स की आवश्यकता होती है , लेकिन डाल () आपको सीधे बाल्टी में एक फाइल के लिए तार लिखने की सुविधा देता है, जो कि लैम्ब्डा कार्यों के लिए एक 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के रूप में एक ही एपीआई के साथ loadऔरdump

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'):।
15

महान विचार। वैसे भी, यह नामकरण सुधार के लिए कुछ स्थान प्रदान करता है।
जन वल्किनस्की

इस अच्छे विचार के प्रस्तावित पुनर्लेखन: gist.github.com/vlcinsky/bbeda4321208aa98745afc29b58e90ac
Jan Vlcinsky

14

एक क्लीनर और संक्षिप्त संस्करण जो मैं किसी दिए गए 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_idऔर aws_secret_access_key) को एक अलग फ़ाइल में रखना चाहिए , उदाहरण के लिए-~/.aws/credentials


AWS क्रेडेंशियल फ़ाइल के लिए Windows समतुल्य स्थान क्या है, क्योंकि Windows समर्थन नहीं करेगा~
Hamman Samuel

1
@ HammanSamuel आप इसे स्टोर कर सकते हैं जैसेC:\Users\username\.aws\credentials
kev

1

यह स्मार्ट-ओपन का उल्लेख करने योग्य है boto3जो बैक-एंड के रूप में उपयोग करता है ।

smart-openअजगर के लिए एक ड्रॉप में प्रतिस्थापन है openकि से फ़ाइलें खोल सकते s3है और साथ ही, ftp, httpऔर कई अन्य प्रोटोकॉल।

उदाहरण के लिए

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
जबकि यह रिस्पॉन्स सूचनात्मक है, यह मूल प्रश्न का उत्तर देने का पालन नहीं करता है - जो कि, कुछ बोटो विधियों के बोटो 3 समकक्ष हैं।
रोबिनहुड 91

1
स्मार्ट ओपन का उपयोग करता है boto3
Uri Goren

1

आप लिखने के लिए नीचे दिए गए कोड का उपयोग कर सकते हैं, उदाहरण के लिए 2019 में S3 के लिए एक छवि। S3 से कनेक्ट करने में सक्षम होने के लिए आपको कमांड का उपयोग करके AWS CLI स्थापित करना होगा pip install awscli, फिर कमांड का उपयोग करके कुछ क्रेडेंशियल्स दर्ज करें 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
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.