Как сгенерировать большие файлы (PDF и CSV) с помощью AppEngine и Datastore?

Когда я только начал разрабатывать этот проект, не было необходимости создавать большие файлы, но теперь это готовый продукт.

Короче говоря, GAE плохо справляется с крупномасштабными манипуляциями с данными или созданием контента. Не считая отсутствия хранилища файлов, даже такая простая вещь, как создание PDF-файла с помощью ReportLab с 1500 записями, похоже, вызывает ошибку DeadlineExceededError. Это простой PDF-файл, состоящий из таблицы.

Я использую следующий код:

    self.response.headers['Content-Type'] = 'application/pdf'
    self.response.headers['Content-Disposition'] = 'attachment; filename=output.pdf'
    doc = SimpleDocTemplate(self.response.out, pagesize=landscape(letter))

    elements = []

    dataset = Voter.all().order('addr_str')

    data = [['#', 'STREET', 'UNIT', 'PROFILE', 'PHONE', 'NAME', 'REPLY', 'YS', 'VOL', 'NOTES', 'MAIN ISSUE']]

    i = 0
    r = 1
    s = 100

    while ( i < 1500 ):
        voters = dataset.fetch(s, offset=i)
        for voter in voters:
            data.append([voter.addr_num, voter.addr_str, voter.addr_unit_num, '', voter.phone, voter.firstname+' '+voter.middlename+' '+voter.lastname ])
            r = r + 1
        i = i + s

    t=Table(data, '', r*[0.4*inch], repeatRows=1 )
    t.setStyle(TableStyle([('ALIGN',(0,0),(-1,-1),'CENTER'),
                           ('INNERGRID', (0,0), (-1,-1), 0.15, colors.black),
                           ('BOX', (0,0), (-1,-1), .15, colors.black),
                           ('FONTSIZE', (0,0), (-1,-1), 8)
                           ]))

    elements.append(t)

    doc.build(elements) 

Ничего особенного, но он задыхается.Есть лучший способ сделать это? Если бы я мог записать в какую-то файловую систему и сгенерировать файл по битам, а затем воссоединить их, это могло бы сработать, но я думаю, что система исключает это.

Мне нужно сделать то же самое для файла CSV, однако предел, очевидно, немного выше, поскольку это просто необработанный вывод.

    self.response.headers['Content-Type'] = 'application/csv'
    self.response.headers['Content-Disposition'] = 'attachment; filename=output.csv'

    dataset = Voter.all().order('addr_str')

    writer = csv.writer(self.response.out,dialect='excel')
    writer.writerow(['#', 'STREET', 'UNIT', 'PROFILE', 'PHONE', 'NAME', 'REPLY', 'YS', 'VOL', 'NOTES', 'MAIN ISSUE'])

    i = 0
    s = 100
    while ( i < 2000 ):
        last_cursor = memcache.get('db_cursor')
        if last_cursor:
            dataset.with_cursor(last_cursor)
        voters = dataset.fetch(s)
        for voter in voters:
            writer.writerow([voter.addr_num, voter.addr_str, voter.addr_unit_num, '', voter.phone, voter.firstname+' '+voter.middlename+' '+voter.lastname])
        memcache.set('db_cursor', dataset.cursor())
        i = i + s
    memcache.delete('db_cursor')

Мы будем очень признательны за любые предложения.

Изменить: possible solutions

Выше я задокументировал три возможных решения, основанных на моем исследовании, плюс предложения и т. Д.

Они не обязательно являются взаимоисключающими и могут быть небольшими вариациями или комбинациями любого из три, однако суть решений есть. Дайте мне знать, какой из них, по вашему мнению, наиболее разумен и может работать лучше всего.

Решение A: Используя mapreduce (или задачи), сериализуйте каждую запись и создайте запись memcache для каждой отдельной записи с ключом с именем ключа. Затем обработайте эти элементы по отдельности в файл pdf / xls. (используйте get_multi и set_multi)

Решение B: Используя задачи, сериализуйте группы записей и загрузите их в базу данных как большой двоичный объект. Затем после обработки всех записей запускайте задачу, которая загружает каждый большой двоичный объект, десериализует их, а затем загружает данные в окончательный файл.

Решение C: Используя mapreduce, получите имена ключей и сохраните их в виде списка или сериализованного большого двоичного объекта. Затем загрузите записи по ключу, что будет быстрее, чем текущий метод загрузки. Если бы я сделал это, что было бы лучше, сохранив их в виде списка (и каковы были бы ограничения ...Я предполагаю, что список из 100 000 будет вне возможностей хранилища данных) или в виде сериализованного большого двоичного объекта (или небольших фрагментов, которые я затем объединяю или обрабатываю)

Заранее благодарим за любой совет.

8
задан etc 17 October 2010 в 06:44
поделиться