Загрузите и проанализируйте CSV-файл с помощью «универсальной новой строки» в python на Google App Engine - PullRequest
11 голосов
/ 17 марта 2011

Я загружаю файл csv / tsv из формы в GAE и пытаюсь проанализировать файл с помощью модуля python csv.

Как описать здесь , загруженные файлы в GAE являются строками.
Таким образом, я обрабатываю загруженную строку объект, подобный файлу:

file = self.request.get('catalog')
catalog = csv.reader(StringIO.StringIO(file),dialect=csv.excel_tab)

Но новые строки в моих файлах не обязательно '\ n' (спасибо excel ..), и это породило ошибку:
Ошибка: символ новой строки отображается в поле без кавычек - вам нужно открыть файл в режиме универсальной новой строки?

Кто-нибудь знает, как использовать StringIO.StringIO для обработки строк как файлов, открытых в universal-newline?

Ответы [ 2 ]

5 голосов
/ 17 марта 2011

Как насчет:

file = self.request.get('catalog')
file  = '\n'.join(file.splitlines())
catalog = csv.reader(StringIO.StringIO(file),dialect=csv.excel_tab)

или, как указано в комментариях, csv.reader() поддерживает ввод из списка, поэтому:

file = self.request.get('catalog')
catalog = csv.reader(file.splitlines(),dialect=csv.excel_tab)

или, если в будущем request.get поддерживает режимы чтения:

file = self.request.get('catalog', 'rU')
catalog = csv.reader(StringIO.StringIO(file),dialect=csv.excel_tab)
4 голосов
/ 19 февраля 2013

Решение, описанное здесь должно работать.Определив класс итератора следующим образом, который загружает большой двоичный объект размером 1 МБ, разбивает строки с помощью .splitlines (), а затем передает строки в CSV-ридер по одной, новые строки могут обрабатываться без необходимости загрузки всего файла.в память.

class BlobIterator:
    """Because the python csv module doesn't like strange newline chars and
    the google blob reader cannot be told to open in universal mode, then
    we need to read blocks of the blob and 'fix' the newlines as we go"""

    def __init__(self, blob_reader):
        self.blob_reader = blob_reader
        self.last_line = ""
        self.line_num = 0
        self.lines = []
        self.buffer = None

    def __iter__(self):
        return self

    def next(self):
        if not self.buffer or len(self.lines) == self.line_num + 1:
            self.buffer = self.blob_reader.read(1048576)  # 1MB buffer
            self.lines = self.buffer.splitlines()
            self.line_num = 0

            # Handle special case where our block just happens to end on a new line
            if self.buffer[-1:] == "\n" or self.buffer[-1:] == "\r":
                self.lines.append("")

        if not self.buffer:
            raise StopIteration

        if self.line_num == 0 and len(self.last_line) > 0:
            result = self.last_line + self.lines[self.line_num] + "\n"
        else:
            result = self.lines[self.line_num] + "\n"

        self.last_line = self.lines[self.line_num + 1]
        self.line_num += 1

        return result

Затем назовите это так:

blob_reader = blobstore.BlobReader(blob_key)
blob_iterator = BlobIterator(blob_reader)
reader = csv.reader(blob_iterator)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...