Próbuję odczytać plik CSV ze znakami akcentowanymi w języku Python (tylko znaki francuskie i / lub hiszpańskie). W oparciu o dokumentację Pythona 2.5 dla csvreadera ( http://docs.python.org/library/csv.html ) wymyśliłem następujący kod do odczytu pliku CSV, ponieważ csvreader obsługuje tylko ASCII.
def unicode_csv_reader(unicode_csv_data, dialect=csv.excel, **kwargs):
# csv.py doesn't do Unicode; encode temporarily as UTF-8:
csv_reader = csv.reader(utf_8_encoder(unicode_csv_data),
dialect=dialect, **kwargs)
for row in csv_reader:
# decode UTF-8 back to Unicode, cell by cell:
yield [unicode(cell, 'utf-8') for cell in row]
def utf_8_encoder(unicode_csv_data):
for line in unicode_csv_data:
yield line.encode('utf-8')
filename = 'output.csv'
reader = unicode_csv_reader(open(filename))
try:
products = []
for field1, field2, field3 in reader:
...
Poniżej znajduje się fragment pliku CSV, który próbuję przeczytać:
0665000FS10120684,SD1200IS,Appareil photo numérique PowerShot de 10 Mpx de Canon avec trépied (SD1200IS) - Bleu
0665000FS10120689,SD1200IS,Appareil photo numérique PowerShot de 10 Mpx de Canon avec trépied (SD1200IS) - Gris
0665000FS10120687,SD1200IS,Appareil photo numérique PowerShot de 10 Mpx de Canon avec trépied (SD1200IS) - Vert
...
Mimo że próbuję zakodować / zdekodować do UTF-8, nadal otrzymuję następujący wyjątek:
Traceback (most recent call last):
File ".\Test.py", line 53, in <module>
for field1, field2, field3 in reader:
File ".\Test.py", line 40, in unicode_csv_reader
for row in csv_reader:
File ".\Test.py", line 46, in utf_8_encoder
yield line.encode('utf-8', 'ignore')
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 68: ordinal not in range(128)
Jak to naprawić?
python
utf-8
csv
character-encoding
Jaskółka oknówka
źródło
źródło
Odpowiedzi:
.encode
Metoda zostanie zastosowana na ciąg Unicode dokonania ciąg bajtów; ale zamiast tego nazywasz to ciągiem bajtów ... w niewłaściwy sposób! Przyjrzyj sięcodecs
modułowi w standardowej bibliotece, acodecs.open
zwłaszcza lepszym ogólnym rozwiązaniom do odczytu plików tekstowych zakodowanych w formacie UTF-8. Jednakcsv
w szczególności w przypadku modułu musisz przekazać dane utf-8 i to właśnie otrzymujesz, więc twój kod może być znacznie prostszy:import csv def unicode_csv_reader(utf8_data, dialect=csv.excel, **kwargs): csv_reader = csv.reader(utf8_data, dialect=dialect, **kwargs) for row in csv_reader: yield [unicode(cell, 'utf-8') for cell in row] filename = 'da.csv' reader = unicode_csv_reader(open(filename)) for field1, field2, field3 in reader: print field1, field2, field3
PS: jeśli okaże się, że twoje dane wejściowe NIE są w utf-8, ale np. W ISO-8859-1, to potrzebujesz "transkodowania" (jeśli chcesz używać utf-8 na
csv
poziomie modułu) , formularzaline.decode('whateverweirdcodec').encode('utf-8')
- ale prawdopodobnie możesz po prostu użyć nazwy istniejącego kodowania wyield
linii w moim kodzie powyżej, zamiast'utf-8'
, jakcsv
to będzie dobrze z bajtami zakodowanymi w ISO-8859- *.źródło
Python 2.X
Istnieje biblioteka unicode-csv, która powinna rozwiązać twoje problemy, z dodatkową korzyścią polegającą na tym, że nie przechodzisz do pisania nowego kodu związanego z CSV.
Oto przykład z ich pliku readme:
>>> 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] é ñ
Python 3.X
W Pythonie 3 jest to obsługiwane po wyjęciu z pudełka przez wbudowany
csv
moduł. Zobacz ten przykład:import csv with open('some.csv', newline='', encoding='utf-8') as f: reader = csv.reader(f) for row in reader: print(row)
źródło
Jeśli chcesz czytać plik CSV z kodowaniem utf-8, minimalistyczne podejście, które polecam, to użycie czegoś takiego:
with open(file_name, encoding="utf8") as csv_file:
Dzięki temu stwierdzeniu możesz później użyć czytnika CSV do pracy.
źródło
encoding
wopen
open('file.csv', 'r', encoding="ISO8859")
Sprawdź również odpowiedź w tym poście: https://stackoverflow.com/a/9347871/1338557
Sugeruje użycie biblioteki o nazwie ucsv.py. Krótki i prosty zamiennik CSV napisany w celu rozwiązania problemu z kodowaniem (utf-8) dla Pythona 2.7. Zapewnia również obsługę csv.DictReader
Edycja : Dodawanie przykładowego kodu, którego użyłem:
import ucsv as csv #Read CSV file containing the right tags to produce fileObj = open('awol_title_strings.csv', 'rb') dictReader = csv.DictReader(fileObj, fieldnames = ['titles', 'tags'], delimiter = ',', quotechar = '"') #Build a dictionary from the CSV file-> {<string>:<tags to produce>} titleStringsDict = dict() for row in dictReader: titleStringsDict.update({unicode(row['titles']):unicode(row['tags'])})
źródło
Używanie tego,
codecs.open
co sugerował Alex Martelli, okazało się przydatne dla mnie.import codecs delimiter = ';' reader = codecs.open("your_filename.csv", 'r', encoding='utf-8') for line in reader: row = line.split(delimiter) # do something with your row ...
źródło
csv
moduł, ale go nie używasz.Link do strony pomocy jest taki sam dla Pythona 2.6 iz tego co wiem, nie było żadnych zmian w module csv od 2.5 (poza poprawkami błędów). Oto kod, który po prostu działa bez kodowania / dekodowania (plik da.csv zawiera te same dane, co dane zmienne ). Zakładam, że twój plik powinien być odczytany poprawnie bez żadnych konwersji.
test.py:
## -*- coding: utf-8 -*- # # NOTE: this first line is important for the version b) read from a string(unicode) variable # import csv data = \ """0665000FS10120684,SD1200IS,Appareil photo numérique PowerShot de 10 Mpx de Canon avec trépied (SD1200IS) - Bleu 0665000FS10120689,SD1200IS,Appareil photo numérique PowerShot de 10 Mpx de Canon avec trépied (SD1200IS) - Gris 0665000FS10120687,SD1200IS,Appareil photo numérique PowerShot de 10 Mpx de Canon avec trépied (SD1200IS) - Vert""" # a) read from a file print 'reading from a file:' for (f1, f2, f3) in csv.reader(open('da.csv'), dialect=csv.excel): print (f1, f2, f3) # b) read from a string(unicode) variable print 'reading from a list of strings:' reader = csv.reader(data.split('\n'), dialect=csv.excel) for (f1, f2, f3) in reader: print (f1, f2, f3)
da.csv:
0665000FS10120684,SD1200IS,Appareil photo numérique PowerShot de 10 Mpx de Canon avec trépied (SD1200IS) - Bleu 0665000FS10120689,SD1200IS,Appareil photo numérique PowerShot de 10 Mpx de Canon avec trépied (SD1200IS) - Gris 0665000FS10120687,SD1200IS,Appareil photo numérique PowerShot de 10 Mpx de Canon avec trépied (SD1200IS) - Vert
źródło
delimiter=','
zamiastdialect=csv.excel
.Warto zauważyć, że jeśli nic nie działało dla ciebie, być może zapomniałeś uciec ze swojej ścieżki.
Na przykład ten kod:
f = open("C:\Some\Path\To\file.csv")
Spowodowałoby błąd:
Aby naprawić, po prostu wykonaj:
f = open("C:\\Some\\Path\\To\\file.csv")
źródło
Patrząc na
Latin-1
tabelę Unicode , widzę kod znaku00E9
„ ŁACIŃSKA MAŁA LITERA E Z OSTRO ”. To jest znak akcentowany w przykładowych danych. Prosty testPython
pokazuje, żeUTF-8
kodowanie dla tego znaku różni się od (prawieUTF-16
) kodowania Unicode .>>> u'\u00e9' u'\xe9' >>> u'\u00e9'.encode('utf-8') '\xc3\xa9' >>>
Proponuję spróbować
encode("UTF-8")
danych Unicode przed wywołaniem oferty specjalnejunicode_csv_reader()
. Samo odczytanie danych z pliku może ukryć kodowanie, więc sprawdź rzeczywiste wartości znaków.źródło
Miałem ten sam problem na innym serwerze, ale zdałem sobie sprawę, że ustawienia regionalne są pomieszane.
export LC_ALL="en_US.UTF-8"
naprawiono problem
źródło