Piszę narzędzie Python, które musi przeanalizować duży, regularnie aktualizowany plik CSV, którego nie kontroluję. Narzędzie musi działać na serwerze z dostępnym tylko Pythonem 2.4. Plik CSV w ogóle nie cytuje wartości pól, ale Python 2.4 version of the csv library nie wydaje mi się, aby wyłączyć cytowanie, pozwala mi tylko ustawić znak cudzysłowu (dialect.quotechar = '"'
lub cokolwiek innego). Jeśli spróbuję ustawić znak cudzysłowu na None
lub pusty łańcuch, pojawia się błąd.Jak wyłączyć cudzysłowy w czytniku CSV Python 2.4?
Mogę to obejść, ustawiając dialect.quotechar
na jakiś "rzadki" znak, ale jest to kruche, ponieważ nie ma znaków ASCII, które mogę absolutnie zagwarantować, nie pojawią się w wartościach pól (z wyjątkiem ogranicznika, ale jeśli Ustawiam dialect.quotechar = dialect.delimiter
, rzeczy idą w przewidywalny sposób.
Jeśli ustawię dialect.quoting
na csv.QUOTE_NONE
, czytnik CSV uszanuje to i nie interpretuje żadnego znaku jako znaku cudzysłowu. Czy istnieje sposób na skopiowanie tego zachowania w Pythonie 2.4?
UPDATE: Dzięki Tryptyk i Mark Roddy za pomoc w zmniejszeniu problemu. Oto najprostszy-case demonstracji:
>>> 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
Problem występuje tylko wtedy, gdy pojawia się pojedynczy znak cudzysłów w ostatnim kolumnie rzędu . Niestety ta sytuacja istnieje w moim zbiorze danych. Zaakceptowałem rozwiązanie Tanja: ręcznie przypisz niedrukowaną postać ("\x07"
lub BEL
) jako cytację. To jest hacky, ale działa, i jeszcze nie widziałem innego rozwiązania, które to robi. Oto demo rozwiązania w akcji:
>>> 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']
W Pythonie 2.5+ ustawienie powołując się csv.QUOTE_NONE byłaby wystarczająca, a wartość quotechar
byłby wtedy znaczenia. (W rzeczywistości uzyskuję swój początkowy dialekt przez csv.Sniffer
, a następnie pomijam wartość metecharną, a nie podklasując csv.Dialect
, ale nie chcę, żeby to było odwrócenie uwagi od prawdziwego problemu, powyższe dwie sesje pokazują, że Sniffer
nie jest problem.)
Wow, dobry pomysł. Ustawienie csv.quotechar = '\ x07' (BEL) wydaje się zdziałać. Nie mogę sobie wyobrazić, w jaki sposób dostaną to do swoich danych CSV. –
Haha - fajny hack. :-) – cdleary
Fajny, hacktastyczny. – Kiv