2015-09-16 2 views
3

У меня есть эта функция для потоковой передачи текстовых файлов:Streaming сгенерированный CSV с Колба

def txt_response(filename, iterator): 
    if not filename.endswith('.txt'): 
     filename += '.txt' 
    filename = filename.format(date=str(datetime.date.today()).replace(' ', '_')) 
    response = Response((_.encode('utf-8')+'\r\n' for _ in iterator), mimetype='text/txt') 
    response.headers['Content-Disposition'] = 'attachment; filename={filename}'.format(filename=filename) 
    return response 

Я работаю, как поток в CSV аналогичным образом. This page приводит пример, но я хочу использовать модуль CSV.

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

ответ

2

В соответствии с этим ответом how do I clear a stringio object? быстрее создать новый объект StringIO для каждой строки в файле, чем метод, который я использую ниже. Однако, если вы все еще не хотите создавать новые StringIO экземпляры можно добиться того, что вы хотите, как это:

import csv 
import StringIO 

from flask import Response 


def iter_csv(data): 
    line = StringIO.StringIO() 
    writer = csv.writer(line) 
    for csv_line in data: 
     writer.writerow(csv_line) 
     line.seek(0) 
     yield line.read() 
     line.truncate(0) 


def csv_response(data): 
    response = Response(iter_csv(data), mimetype='text/csv') 
    response.headers['Content-Disposition'] = 'attachment; filename=data.csv' 
    return response 

Если вы просто хотите, чтобы поток обратно результаты, как они созданы csv.writer вы можете создать собственный объект реализуя интерфейс, который ожидает автор.

import csv 

from flask import Response 


class Line(object): 
    def __init__(self): 
     self._line = None 
    def write(self, line): 
     self._line = line 
    def read(self): 
     return self._line 


def iter_csv(data): 
    line = Line() 
    writer = csv.writer(line) 
    for csv_line in data: 
     writer.writerow(csv_line) 
     yield line.read() 


def csv_response(data): 
    response = Response(iter_csv(data), mimetype='text/csv') 
    response.headers['Content-Disposition'] = 'attachment; filename=data.csv' 
    return response 
Смежные вопросы