Я пишу утилиту Python, которая должна анализировать большой, регулярно обновляемый CSV файл, который я не контролирую. Утилита должна запускаться на сервере с доступным только Python 2.4. Файл CSV вообще не указывает значения полей, но версия библиотеки csv версии 2.4 для Python не кажется мне каким-либо образом off quoting, он просто позволяет мне задать символ кавычки (dialect.quotechar = '"'
или что-то еще). Если я попытаюсь установить символ кавычки на None
или пустую строку, я получаю сообщение об ошибке.
Я могу обойти это, установив dialect.quotechar
на некоторый "редкий" символ, но это хрупкое, так как нет символа ASCII, который я могу абсолютно гарантировать, не будет отображаться в значениях поля (кроме разделителя, но если я устанавливаю dialect.quotechar = dialect.delimiter
, вещи идут предсказуемо haywire).
В Python 2.5 и более поздние версии, если я установил dialect.quoting
в csv.QUOTE_NONE
, читатель CSV уважает это и не интерпретирует никаких символ как символ кавычек. Есть ли способ дублировать это поведение в Python 2.4?
ОБНОВЛЕНИЕ. Спасибо Триптих и Марк Родди за то, что они помогли сузить проблему. Здесь простейшая демонстрация:
>>> import csv
>>> import StringIO
>>> data = """
... 1,2,3,4,"5
... 1,2,3,4,5
... """
>>> reader = csv.reader(StringIO.StringIO(data))
>>> for i in reader: print i
...
[]
Traceback (most recent call last):
File "<stdin>", line 1, in ?
_csv.Error: newline inside string
Проблема возникает только при наличии в последнем столбце строки одного символа двойной кавычки. К сожалению, эта ситуация существует в моем наборе данных. Я принял решение Tanj: вручную назначить непечатаемый символ ("\x07"
или BEL
) в качестве катчара. Это хаки, но это работает, и я еще не видел другого решения. Вот демонстрация решения в действии:
>>> import csv
>>> import StringIO
>>> class MyDialect(csv.Dialect):
... quotechar = '\x07'
... delimiter = ','
... lineterminator = '\n'
... doublequote = False
... skipinitialspace = False
... quoting = csv.QUOTE_NONE
... escapechar = '\\'
...
>>> dialect = MyDialect()
>>> data = """
... 1,2,3,4,"5
... 1,2,3,4,5
... """
>>> reader = csv.reader(StringIO.StringIO(data), dialect=dialect)
>>> for i in reader: print i
...
[]
['1', '2', '3', '4', '"5']
['1', '2', '3', '4', '5']
В Python 2.5+ достаточно указать значение csv.QUOTE_NONE, и значение quotechar
тогда будет неактуальным. (Я фактически получаю свой начальный диалект через csv.Sniffer
, а затем переопределяя значение катчара, а не подклассированием csv.Dialect
, но я не хочу, чтобы это было отвлечением от реальной проблемы, эти две сессии показывают, что Sniffer
не проблема.)