Использование модуля Python CSV для обновления файла - PullRequest
4 голосов
/ 04 января 2010

Я использую модуль Python CSV для извлечения данных из CSV, который постоянно обновляется внешним инструментом. Я столкнулся с проблемой, когда, когда я достигаю конца файла, я получаю ошибку StopIteration, однако, я хотел бы, чтобы скрипт продолжал цикл в ожидании добавления дополнительных строк внешним инструментом.

Что я придумал, чтобы сделать это:

f = open('file.csv')
csvReader = csv.reader(f, delimiter=',')
while 1:
    try:
        doStuff(csvReader.next())
    except StopIteration:
        depth = f.tell()
        f.close()
        f = open('file.csv')
        f.seek(depth)
        csvReader = csv.reader(f, delimiter=',')

У этого есть предполагаемая функциональность, но это также кажется ужасным. Цикл после перехвата StopIteration невозможен, так как после того, как StopItered выбрасывается, он будет бросать StopIteration при каждом последующем вызове next (). Кто-нибудь есть какие-либо предложения о том, как реализовать это таким образом, что мне не нужно делать это глупо рассказывать и искать? Или используйте другой модуль Python, который может легко поддерживать эту функцию.

Ответы [ 3 ]

4 голосов
/ 04 января 2010

Ваша проблема не с читателем CSV, а с самим объектом файла. Возможно, вам все еще придется выполнять сумасшедшие движения, которые вы делаете в приведенном выше фрагменте, но было бы лучше создать оболочку или подкласс файлового объекта, которая сделает это за вас, и использовать это с вашим CSV-ридером. Это сохраняет сложность изолированной от вашего кода обработки CSV.

Например (предупреждение: непроверенный код):

class ReopeningFile(object):
    def __init__(self, filename):
        self.filename = filename
        self.f = open(self.filename)

    def next(self):
        try:
            self.f.next()
        except StopIteration:
            depth = self.f.tell()
            self.f.close()
            self.f = open(self.filename)
            self.f.seek(depth)
            # May need to sleep here to allow more data to come in
            # Also may need a way to signal a real StopIteration
            self.next()

    def __iter__(self):
        return self

Тогда ваш основной код становится проще, так как он избавлен от необходимости управлять повторным открытием файла (обратите внимание, что вам также не нужно перезапускать csv_reader при каждом перезапуске файла:

import csv
csv_reader = csv.reader(ReopeningFile('data.csv'))
for each in csv_reader:
    process_csv_line(each)
2 голосов
/ 04 января 2010

Производители-потребители могут быть немного хитрыми. Как насчет использования байтов поиска и чтения? Как насчет использования именованного канала?

Черт, почему бы не общаться через локальный сокет?

0 голосов
/ 04 января 2010

Вам редко нужно явно ловить StopIteration. Сделайте это:

for row in csvReader:
    doStuff(row)

Что касается определения, когда в файл записываются новые строки, вы можете либо открыть процесс tail -f, либо записать код Python для того, что делает tail -f. (Это не сложно; это просто stat файл в секунду, чтобы увидеть, если он изменился. Вот исходный код C tail. )

РЕДАКТИРОВАТЬ: К сожалению, всплывающее tail -f не работает, как я ожидал в Python 2.x. Кажется, что перебор строк файла реализован с использованием fread и большого буфера, даже если предполагается, что файл небуферизован (например, когда subprocess.py создает файл, передавая bufsize = 0) Но всплывающее tail было бы в любом случае слегка уродливым хаком.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...