Использование резервной памяти S3 в Python - PullRequest
1 голос
/ 17 марта 2010

В настоящее время я использую WebFaction для своего хостинга с базовым пакетом, который дает нам 80 МБ ОЗУ. Это более чем достаточно для наших нужд на данный момент, кроме наших резервных копий. Мы делаем собственные резервные копии на S3 один раз в день.

Процесс резервного копирования выглядит следующим образом: выгрузите базу данных, tar.gz все файлы в одну резервную копию с правильной датой резервного копирования, загрузите на S3 с помощью библиотеки python, предоставленной Amazon.

К сожалению, кажется (хотя я не знаю это наверняка), что либо мой код для чтения файла, либо код S3 загружает весь файл в память. Поскольку размер файла составляет около 320 МБ (для сегодняшнего резервного копирования), он использует около 320 МБ только для резервного копирования. Это приводит к тому, что WebFaction завершает все наши процессы, что означает, что резервное копирование не происходит и наш сайт не работает.

Так вот в чем вопрос: есть ли способ не загружать весь файл в память, или есть какие-то другие библиотеки python S3, которые намного лучше с использованием оперативной памяти. В идеале это должно быть максимум 60MB! Если это невозможно, как я могу разделить файл и загрузить отдельные части?

Спасибо за вашу помощь.

Это часть кода (в моем скрипте резервного копирования), которая вызвала завершение процессов:

filedata = open(filename, 'rb').read()
content_type = mimetypes.guess_type(filename)[0]
if not content_type:
    content_type = 'text/plain'
print 'Uploading to S3...'
response = connection.put(BUCKET_NAME, 'daily/%s' % filename, S3.S3Object(filedata), {'x-amz-acl': 'public-read', 'Content-Type': content_type})

Ответы [ 2 ]

2 голосов
/ 10 марта 2011

Уже немного поздно, но мне пришлось решить ту же проблему, поэтому вот мой ответ.

Краткий ответ: в Python 2.6+ да! Это потому, что httplib поддерживает файловые объекты начиная с v2.6. Так что все, что вам нужно, это ...

fileobj = open(filename, 'rb')
content_type = mimetypes.guess_type(filename)[0]
if not content_type:
    content_type = 'text/plain'
print 'Uploading to S3...'
response = connection.put(BUCKET_NAME, 'daily/%s' % filename, S3.S3Object(fileobj), {'x-amz-acl': 'public-read', 'Content-Type': content_type})

Длинный ответ ...

Библиотека S3.py использует httplib Python для выполнения connection.put() HTTP-запросов. В источнике видно, что он просто передает аргумент data в соединение httplib.

С S3.py ...

    def _make_request(self, method, bucket='', key='', query_args={}, headers={}, data='', metadata={}):

        ...

        if (is_secure):
            connection = httplib.HTTPSConnection(host)
        else:
            connection = httplib.HTTPConnection(host)

        final_headers = merge_meta(headers, metadata);
        # add auth header
        self._add_aws_auth_header(final_headers, method, bucket, key, query_args)

        connection.request(method, path, data, final_headers) # <-- IMPORTANT PART
        resp = connection.getresponse()
        if resp.status < 300 or resp.status >= 400:
            return resp
        # handle redirect
        location = resp.getheader('location')
        if not location:
            return resp
        ...

Если мы посмотрим на документацию httplib python , мы увидим, что ...

HTTPConnection.request(method, url[, body[, headers]])

Это отправит запрос на сервер, используя метод HTTP-запроса и URL селектора. Если аргумент body присутствует, это должна быть строка данных для отправки после окончания заголовков. Альтернативно, это может быть открытый файловый объект, и в этом случае содержимое файла отправляется; Этот файловый объект должен поддерживать методы fileno () и read (). Заголовок Content-Length автоматически устанавливается на правильное значение. Аргумент headers должен отображать дополнительные заголовки HTTP для отправки вместе с запросом.

Изменено в версии 2.6: тело может быть файловым объектом.

0 голосов
/ 17 марта 2010

не читает весь файл в вашу переменную filedata. Вы можете использовать цикл, а затем просто прочитать ~ 60 МБ и отправить их в amazon.

backup = open(filename, 'rb')
while True:
    part_of_file = backup.read(60000000) # not exactly 60 MB....
    response = connection.put() # submit part_of_file here to amazon
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...