В чем разница между S3.Client.upload_file () и S3.Client.upload_fileobj ()? - PullRequest
0 голосов
/ 14 сентября 2018

Согласно S3.Client.upload_file и S3.Client.upload_fileobj , upload_fileobj может звучать быстрее. Но кто-нибудь знает специфику? Должен ли я просто загрузить файл или открыть файл в двоичном режиме, чтобы использовать upload_fileobj? Другими словами,

import boto3

s3 = boto3.resource('s3')

### Version 1
s3.meta.client.upload_file('/tmp/hello.txt', 'mybucket', 'hello.txt')

### Version 2
with open('/tmp/hello.txt', 'rb') as data:
    s3.upload_fileobj(data, 'mybucket', 'hello.txt')

Версия 1 или 2 лучше? Есть ли разница?

Ответы [ 3 ]

0 голосов
/ 14 сентября 2018

TL; DR

с точки зрения скорости, оба метода будут работать примерно одинаково, оба написаны на python, и узким местом будет либо disk-io (чтение файла с диска), либо network-io (записьto s3).

  • используйте upload_file() при написании кода, который обрабатывает загрузку файлов только с диска.
  • используйте upload_fileobj() при написании универсального кода для обработки загрузки s3, которая может бытьможет быть использован в будущем не только для файла с дискабиблиотека, что когда кто-то использует термин fileobj, она означает файлоподобный объект .Есть даже некоторые библиотеки, предоставляющие функции, которые могут принимать путь к файлу (str) или fileobj (файлоподобный объект) в качестве одного и того же параметра.

    при использовании файлового объекта ваш код не ограничивается только диском, например:

    1. например, вы можете копировать данные из одного объекта s3 в другой потоковым способом (без использования дискового пространства или замедления процесса чтения / записи ввода-вывода на диск).

    2. вы можете (де) сжимать или дешифровать данные на лету при записи объектов в S3

    , например, с использованием модуля python gzip сфайлоподобный объект в общем виде:

    import gzip, io
    
    def gzip_greet_file(fileobj):
        """write gzipped hello message to a file"""
        with gzip.open(filename=fileobj, mode='wb') as fp:
            fp.write(b'hello!')
    
    # using opened file
    gzip_greet_file(open('/tmp/a.gz', 'wb'))
    
    # using filename from disk
    gzip_greet_file('/tmp/b.gz')
    
    # using io buffer
    file = io.BytesIO()
    gzip_greet_file(file)
    file.seek(0)
    print(file.getvalue())
    

    tarfile , с другой стороны, имеет два параметра file & fileobj:

    tarfile.open(name=None, mode='r', fileobj=None, bufsize=10240, **kwargs)
    

    Пример сжатия на лету с s3.upload_fileobj()

    import gzip, boto3
    
    s3 = boto3.resource('s3')
    
    
    def upload_file(fileobj, bucket, key, compress=False):
        if compress:
            fileobj = gzip.GzipFile(fileobj=fileobj, mode='rb')
            key = key + '.gz'
        s3.upload_fileobj(fileobj, bucket, key)
    
0 голосов
/ 14 сентября 2018

Главное с upload_fileobj заключается в том, что файловый объект не обязательно должен храниться на локальном диске, а может быть представлен как файловый объект в ОЗУ.

Python имеет для этой цели стандартный библиотечный модуль .

Код будет выглядеть так:

import io
fo = io.BytesIO(b'my data stored as file object in RAM')
s3.upload_fileobj(fo, 'mybucket', 'hello.txt')

В этом случае он будет работать быстрее, поскольку вам не нужно читать с локального диска.

0 голосов
/ 14 сентября 2018

Ни лучше, потому что они не сопоставимыХотя конечный результат один и тот же (объект загружается на S3), они получают этот объект совершенно по-разному.Один ожидает, что вы предоставите путь на диске для файла для загрузки, в то время как другой ожидает, что вы предоставите файлоподобный объект.

Если у вас есть файл на диске и вы хотите загрузить его, используйте upload_file.Если у вас есть файлоподобный объект (который может в конечном итоге состоять из множества вещей, включая открытый файл, поток, сокет, буфер, строку), тогда используйте upload_fileobj.

A 'файловоподобный объект'в этом контексте все, что реализует метод read и возвращает байты.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...