2015-06-25 5 views
0

У меня есть следующий сценарий, чтобы прочитать UTF-8 CSV:CSV dictReader кодирование не исправить

def readCSV(f, bdgs): 
with open(f) as csvfile: 
    reader = csv.DictReader(csvfile, delimiter=';') 
    for row in reader: 
     for key, val in row.iteritems(): 
      print type(key), key,':',type(val),val 
     print type(row), row 
     if row['OBJECTID'] is not '': 
      # do some magic 

, которые дают это:

processing the following files: ['Fenetre.csv'] 
<type 'str'> Type de fenêtre_uniqueid : <type 'str'> uid-100 
<type 'str'> Type de fenêtre_CheckDelete : <type 'str'> 
<type 'str'> Type de fenêtre_Nom : <type 'str'> Fenetre 2006-2010 
<type 'str'> Type de fenêtre_Intercalaire : <type 'str'> 1 
<type 'str'> Liste des fenêtres_Hauteur : <type 'str'> 3.29 
<type 'str'> OBJECTID : <type 'str'> 3760 
<type 'str'> Liste des fenêtres_Nb vantaux : <type 'str'> 2 
<type 'str'> Liste des fenêtres_Façade : <type 'str'> uid-001-AW1 
<type 'str'> Type de fenêtre_Cadre : <type 'str'> 7 
<type 'str'> Type de fenêtre_vitrage : <type 'str'> 4 
<type 'str'> Liste des fenêtres_Part cadre : <type 'str'> 20 
<type 'str'> Liste des fenêtres_Nom : <type 'str'> f1 
<type 'str'> Liste des fenêtres_Nombre : <type 'str'> 1 
<type 'str'> Liste des fenêtres_Ombrage1 : <type 'str'> uid-201 
<type 'str'> Liste des fenêtres_Largeur : <type 'str'> 1.55 
<type 'str'> Liste des fenêtres_Ombrage2 : <type 'str'> 
<type 'str'> Liste des fenêtres_CheckDelete : <type 'str'> 
<type 'str'> Liste des fenêtres_Type de fenêtre : <type 'str'> uid-100 
<type 'dict'> {'Type de fen\xc3\xaatre_uniqueid': 'uid-100', 'Type de fen\xc3\xaatre_CheckDelete': '', 'Type de fen\xc3\xaatre_Nom': 'Fenetre 2006-2010', 'Type de fen\xc3\xaatre_Intercalaire': '1', 'Liste des fen\xc3\xaatres_Hauteur': '3.29', '\xef\xbb\xbfOBJECTID': '3760', 'Liste des fen\xc3\xaatres_Nb vantaux': '2', 'Liste des fen\xc3\xaatres_Fa\xc3\xa7ade': 'uid-001-AW1', 'Type de fen\xc3\xaatre_Cadre': '7', 'Type de fen\xc3\xaatre_vitrage': '4', 'Liste des fen\xc3\xaatres_Part cadre': '20', 'Liste des fen\xc3\xaatres_Nom': 'f1', 'Liste des fen\xc3\xaatres_Nombre': '1', 'Liste des fen\xc3\xaatres_Ombrage1': 'uid-201', 'Liste des fen\xc3\xaatres_Largeur': '1.55', 'Liste des fen\xc3\xaatres_Ombrage2': '', 'Liste des fen\xc3\xaatres_CheckDelete': '', 'Liste des fen\xc3\xaatres_Type de fen\xc3\xaatre': 'uid-100'} 
Traceback (most recent call last): 
    File "./oba.py", line 120, in <module> 
    sys.exit(main()) 
    File "./oba.py", line 115, in main 
    readCSV(f,out) 
    File "./oba.py", line 37, in readCSV 
    if row['OBJECTID'] is not '': 
KeyError: 'OBJECTID' 

, если вы посмотрите на последнюю строку до трассировки стека , вы видите, что хотя кодировка для ключей и строк значений в первой строке все правильно. dict не сохраняет ключ/значения с надлежащим кодированием. Отсюда и ошибка.

Для того, чтобы исправить эту проблему, я попытался это:

def unicodeDictReader(utf8_data, **kwargs): 
    csv_reader = csv.DictReader(utf8_data, **kwargs) 
    for row in csv_reader: 
     yield {unicode(key, 'utf-8') : unicode(value, 'utf-8') for key, value in row.iteritems()} 

def readCSV(f, bdgs): 
    js=getJSONmap() 
    with open(f) as csvfile: 
     reader = unicodeDictReader(csvfile, delimiter=';') 
     for row in reader: 
      for key, val in row.iteritems(): 
       print type(key), key,':',type(val),val 
      print type(row), row 
      if row['OBJECTID'] is not '': 

, которые дают эту:

<type 'unicode'> Type de fenêtre_Cadre : <type 'unicode'> 7 
<type 'unicode'> Liste des fenêtres_Hauteur : <type 'unicode'> 3.29 
<type 'unicode'> Type de fenêtre_uniqueid : <type 'unicode'> uid-100 
<type 'unicode'> Liste des fenêtres_Nom : <type 'unicode'> f1 
<type 'unicode'> OBJECTID : <type 'unicode'> 3760 
<type 'unicode'> Type de fenêtre_Intercalaire : <type 'unicode'> 1 
<type 'unicode'> Liste des fenêtres_Ombrage1 : <type 'unicode'> uid-201 
<type 'unicode'> Liste des fenêtres_Largeur : <type 'unicode'> 1.55 
<type 'unicode'> Liste des fenêtres_Part cadre : <type 'unicode'> 20 
<type 'unicode'> Liste des fenêtres_Type de fenêtre : <type 'unicode'> uid-100 
<type 'unicode'> Type de fenêtre_Nom : <type 'unicode'> Fenetre 2006-2010 
<type 'unicode'> Liste des fenêtres_CheckDelete : <type 'unicode'> 
<type 'unicode'> Liste des fenêtres_Nb vantaux : <type 'unicode'> 2 
<type 'unicode'> Type de fenêtre_CheckDelete : <type 'unicode'> 
<type 'unicode'> Type de fenêtre_vitrage : <type 'unicode'> 4 
<type 'unicode'> Liste des fenêtres_Façade : <type 'unicode'> uid-001-AW1 
<type 'unicode'> Liste des fenêtres_Ombrage2 : <type 'unicode'> 
<type 'unicode'> Liste des fenêtres_Nombre : <type 'unicode'> 1 
<type 'dict'> {u'Type de fen\xeatre_Cadre': u'7', u'Liste des fen\xeatres_Hauteur': u'3.29', u'Type de fen\xeatre_uniqueid': u'uid-100', u'Liste des fen\xeatres_Nom': u'f1', u'\ufeffOBJECTID': u'3760', u'Type de fen\xeatre_Intercalaire': u'1', u'Liste des fen\xeatres_Ombrage1': u'uid-201', u'Liste des fen\xeatres_Largeur': u'1.55', u'Liste des fen\xeatres_Part cadre': u'20', u'Liste des fen\xeatres_Type de fen\xeatre': u'uid-100', u'Type de fen\xeatre_Nom': u'Fenetre 2006-2010', u'Liste des fen\xeatres_CheckDelete': u'', u'Liste des fen\xeatres_Nb vantaux': u'2', u'Type de fen\xeatre_CheckDelete': u'', u'Type de fen\xeatre_vitrage': u'4', u'Liste des fen\xeatres_Fa\xe7ade': u'uid-001-AW1', u'Liste des fen\xeatres_Ombrage2': u'', u'Liste des fen\xeatres_Nombre': u'1'} 
Traceback (most recent call last): 
    File "./oba.py", line 120, in <module> 
    sys.exit(main()) 
    File "./oba.py", line 115, in main 
    readCSV(f,out) 
    File "./oba.py", line 37, in readCSV 
    if row['OBJECTID'] is not '': 
KeyError: 'OBJECTID' 

который теперь делает меня запутать, как к тому, что происходит за кулисами с кодировкой:

  • Как исправить это, не ища «\ ufeffOBJECTID» в моем dict?
  • Почему в моей второй попытке питон признает, что он считывает данные utf-8 (unicode) в строке, но все же отображает его неправильно, когда я печатаю строку как dict?
  • что проблема с печатью/хранением unicode dicts в python? Ожидается ли такое поведение для любого контейнера?

Может ли кто-нибудь с более глубоким пониманием кодирования дать мне некоторую информацию о том, что происходит за кулисами здесь?

Спасибо.

EDIT: также стоит отметить, что в заголовке файла я объявил кодировку как utf-8. (Т.е. "# - - кодирование: UTF-8 - -"), и я бегу v2.7.6

+0

любой шанс, что вы могли бы поставить ссылку на тест CSV, который вызывает эти ошибки? – wilfo

+0

уверен. [this] (https://dl.dropboxusercontent.com/u/105505396/Fenetre.csv) - это файл, который я использую в примере выше. – bny

+0

. Тест 'some_object is not ''' очень опасен, потому что нет гарантии, что каждая пустая строка является тем же самым объектом. Таким образом, этот тест может завершиться неудачно, даже если 'some_object' является пустой строкой. Или другими словами: если он работает так, как вы его написали, он более или менее «случайно» - деталь реализации. – BlackJack

ответ

2

How do I fix this without having to look for "\ufeffOBJECTID" in my dict?

utf-8-sig Используйте вместо utf-8 для декодирования.Он автоматически удаляет код BOM при декодировании строки байта с кодировкой UTF-8.

Why in my second attempt is python acknowledging that it reads utf-8 (unicode) data in the row but still displays it the wrong way when I print the row as a dict?

печати контейнеры использует repr() при печати элементов контейнера. Это значит, что вы можете видеть фактические данные в строках. print элементы контейнера, чтобы увидеть их «симпатичную» версию.

Is that a problem with printing/storing unicode dicts in python ?

Это не проблема. Это всего лишь метод отображения. Данные в строках одинаковы.

Is this behavior expected for any container?

Да.

Кроме того, не используйте is для проверки пустой строки. Использование:

if row['OBJECTID'] != '': 

или лучше, так как пустые строки считаются ложными:

if row['OBJECTID']: 
+0

Привет. Это работает, удаляет спецификацию в начале. Благодаря! Однако специальные символы, такие как «ê», все еще хранятся и отображаются как «\ xea» и т. Д. В коллекции. Любая идея на этом? Пример: u'Liste des fen \ xeatres_Fa \ xe7ade 'вместо' Liste des fenêtres_Façade ' – bny

+0

Это просто опция отображения. Контейнеры цитируют строки и избегают символов, отличных от ASCII. Распечатайте элементы в контейнере, чтобы увидеть символы. –

1

Я запускал скрипт с вашим кодом и получил следующий результат:

<type 'unicode'> Type de fenêtre_Cadre : <type 'unicode'> 7 
<type 'unicode'> Liste des fenêtres_Hauteur : <type 'unicode'> 3.29 
<type 'unicode'> Type de fenêtre_uniqueid : <type 'unicode'> uid-100 
<type 'unicode'> Liste des fenêtres_Nom : <type 'unicode'> f1 
<type 'unicode'> OBJECTID : <type 'unicode'> 3760 

Примечание что при вставке в это текстовое поле StackOverflow уничтожает символ юникода до OBJECTID.

В ответ на ваши вопросы, я думаю, что такое поведение является разумным, поскольку 'OBJECTID' на самом деле не в row (а, '\ufeffOBJECTID' есть)

Почему это так, что Python печатает всю строку с юникод символов, вероятно, о том, как __repr__' of dict` реализуется

, если вы хотите избавиться от Юникода я suugest используя unidecode или пакет сортировки, а затем вы можете обратиться непосредственно к OBJECTID

Я надеюсь, что эта помощь объясняет это

+0

Я вижу, куда вы идете. Но тогда это должно быть только проблема с печатью ... Это не должно вызывать испытание, если «OBJECTID» находится в коллекции (т. Е. В моем коде :) 'if row ['OBJECTID'] не является ' : ' ' KeyError: 'OBJECTID''. Этого не должно быть, так как «OBJECTID» действительно является ключом в dict ... – bny

+0

Не уверен, что я следую за вами мышлением, но если вы хотите узнать, находится ли ключ в коллекции, вы должны написать 'if ' OBJECTID 'в строке: ... '. И в этом конкретном случае результатом будет 'False', так как' '\ ufeffOBJECTID'' находится в dict, а не' 'OBJECTID'' – wilfo

+0

точно! Итак, как мне помещать 'OBJECTID', 'Type de fenêtre_Cadre' и т. Д. Вместо u '\ ufeffOBJECTID', u'Type de fen \ xeatre_Cadre 'и т. Д. В коллекции? – bny

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

  • Нет связанных вопросов^_^