2014-01-31 2 views
4

У меня возникли проблемы с чтением в CSV строки Юникода в питон-unicodescv:unicodecsv читатель из строки unicode не работает?

>>> import unicodecsv, StringIO 
>>> f = StringIO.StringIO(u'é,é') 
>>> r = unicodecsv.reader(f, encoding='utf-8') 
>>> row = r.next() 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "/Users/guy/test/.env/lib/python2.7/site-packages/unicodecsv/__init__.py", line 101, in next 
    row = self.reader.next() 
UnicodeEncodeError: 'ascii' codec can't encode character u'\xe9' in position 0: ordinal not in range(128) 

Я предполагаю, что это проблема с тем, как преобразовать свою юникод строку в файл StringIO каким-то образом? Пример на странице GitHub питон-unicodecsv работает отлично:

>>> import unicodecsv 
>>> from cStringIO import StringIO 
>>> f = StringIO() 
>>> w = unicodecsv.writer(f, encoding='utf-8') 
>>> w.writerow((u'é', u'ñ')) 
>>> f.seek(0) 
>>> r = unicodecsv.reader(f, encoding='utf-8') 
>>> row = r.next() 
>>> print row[0], row[1] 
é ñ 

Попытка мой код с cStringIO терпит неудачу как cStringIO не может принять Юникода

>>> from cStringIO import StringIO 
>>> f = StringIO(u'é') 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
UnicodeEncodeError: 'ascii' codec can't encode character u'\xe9' in position 0: ordinal not in range(128) 
(так почему пример работает, я не знаю!)

Мне нужно принять форматированный вход в формате UTF-8 CSV из поля формы текстового поля, поэтому он не может просто считываться из файла.

Любые идеи?

ответ

7

Файл unicodecsv читает и декодирует байтовые строки для вас. Вместо этого вы передаете его unicode. На выходе ваши значения в кодировке unicode кодируются для байтов для вас, используя сконфигурированный кодек.

Кроме того, cStringIO.StringIO может обрабатывать только закодированные байтовые строки, в то время как класс чисто питон StringIO.StringIO счастливо обрабатывает unicode значения, если они байтовые строки.

Раствор для закодировать ваши ценности Юникода, прежде чем положить их в StringIO объект:

>>> import unicodecsv, StringIO, cStringIO 
>>> f = StringIO.StringIO(u'é,é'.encode('utf8')) 
>>> r = unicodecsv.reader(f, encoding='utf-8') 
>>> next(r) 
[u'\xe9', u'\xe9'] 
>>> f = cStringIO.StringIO(u'é,é'.encode('utf8')) 
>>> r = unicodecsv.reader(f, encoding='utf-8') 
>>> next(r) 
[u'\xe9', u'\xe9'] 
+0

Отлично. Отличный ответ и быстрый. Должен любить ТАК :) –

Смежные вопросы