Потоковая передача огромного файла gzip из s3 с использованием boto3 python [duplicate]

Я нахожу, что более общим решением является не указание «N» коммитов, а скорее идентификатор ветки / фиксации, который вы хотите раздавить поверх. Это менее подвержено ошибкам, чем подсчет коммиттов до определенного коммита - просто укажите тег напрямую или если вы действительно хотите подсчитать, вы можете указать HEAD ~ N.

В моем рабочем процессе я запускаю ветви, и моя первая фиксация на этой ветке суммирует цель (т.е. обычно это то, что я буду нажимать как «окончательное» сообщение для этой функции в публичный репозиторий.) Поэтому, когда я закончил, все, что я хочу сделать, это git squash master назад к первому сообщению, а затем я готов нажать.

Я использую псевдоним:

squash = !EDITOR="\"_() { sed -n 's/^pick //p' \"\\$1\"; sed -i .tmp '2,\\$s/^pick/f/' \"\\$1\"; }; _\"" git rebase -i

Это сбрасывает историю, раздавленную до того, как она это сделает - это дает вам возможность восстановиться, захватив старый идентификатор фиксации с консоли, если вы хотите вернуться. (Пользователи Solaris отмечают, что используют параметр GNU sed -i, пользователи Mac и Linux должны быть в порядке с этим.)

15
задан joemastersemison 2 October 2011 в 07:09
поделиться

4 ответа

Объект Key в boto, который представляет объект на S3, можно использовать как итератор, чтобы вы могли сделать что-то вроде этого:

>>> import boto
>>> c = boto.connect_s3()
>>> bucket = c.lookup('garnaat_pub')
>>> key = bucket.lookup('Scan1.jpg')
>>> for bytes in key:
...   write bytes to output stream

Или, как в случае ваш пример:

>>> shutil.copyfileobj(key, rsObject.stream())
17
ответ дан garnaat 25 August 2018 в 02:47
поделиться

Я полагаю, что, по крайней мере, некоторые из людей, которые видят этот вопрос, будут похожи на меня, и мне захочется создать поток из boto по строке (или запятую через запятую или любой другой разделитель). Вот простой способ сделать это:

def getS3ResultsAsIterator(self, aws_access_info, key, prefix):        
    s3_conn = S3Connection(**aws_access)
    bucket_obj = s3_conn.get_bucket(key)
    # go through the list of files in the key
    for f in bucket_obj.list(prefix=prefix):
        unfinished_line = ''
        for byte in f:
            byte = unfinished_line + byte
            #split on whatever, or use a regex with re.split()
            lines = byte.split('\n')
            unfinished_line = lines.pop()
            for line in lines:
                yield line

Ответ @ garnaat выше по-прежнему велик и на 100% прав. Надеюсь, мой все еще помогает кому-то.

20
ответ дан Eli 25 August 2018 в 02:47
поделиться

Это мое решение обтекающего потокового тела:

import io
class S3ObjectInterator(io.RawIOBase):
    def __init__(self, bucket, key):
        """Initialize with S3 bucket and key names"""
        self.s3c = boto3.client('s3')
        self.obj_stream = self.s3c.get_object(Bucket=bucket, Key=key)['Body']

    def read(self, n=-1):
        """Read from the stream"""
        return self.obj_stream.read() if n == -1 else self.obj_stream.read(n)

Пример использования:

obj_stream = S3ObjectInterator(bucket, key)
for line in obj_stream:
    print line
2
ответ дан jzhou 25 August 2018 в 02:47
поделиться

Другие ответы в этой теме связаны с boto, но S3.Object больше не повторяется в boto3. Таким образом, следующее НЕ РАБОТАЕТ, оно выдает сообщение об ошибке TypeError: 's3.Object' object is not iterable:

    s3 = boto3.session.Session(profile_name=my_profile).resource('s3')
    s3_obj = s3.Object(bucket_name=my_bucket, key=my_key)

    with io.FileIO('sample.txt', 'w') as file:
        for i in s3_obj:
            file.write(i)

В boto3 содержимое объекта доступно в S3.Object.get()['Body'], которое также не является итерируемым, поэтому следующий еще НЕ РАБОТАЕТ:

    body = s3_obj['Body']
    with io.FileIO('sample.txt', 'w') as file:
        for i in body:
            file.write(i)

Итак, альтернативой является использование метода чтения, но это загружает объект WHOLE S3 в память, который при работе с большими файлами не всегда возможен:

    body = s3_obj['Body']
    with io.FileIO('sample.txt', 'w') as file:
        for i in body.read():
            file.write(i)

Но метод read позволяет передать в amt параметр, определяющий количество байтов, которые мы хотим прочитать из базового потока. Этот метод можно многократно вызывать до тех пор, пока весь поток не будет прочитан:

    body = s3_obj['Body']
    with io.FileIO('sample.txt', 'w') as file:
        while file.write(body.read(amt=512)):
            pass

Копаем в код botocore.response.StreamingBody, понимаем, что базовый поток также доступен, поэтому мы могли бы выполнять итерацию следующим образом:

    body = s3_obj['Body']
    with io.FileIO('sample.txt', 'w') as file:
        for b in body._raw_stream:
            file.write(b)

В то время как googling я также видел некоторые ссылки, которые могут быть использованы, но я не пробовал:

22
ответ дан Wakahiu Njenga 25 August 2018 в 02:47
поделиться
Другие вопросы по тегам:

Похожие вопросы: