Python ile UTF8 CSV dosyası okumak


94

Python ile aksanlı karakterler içeren bir CSV dosyası okumaya çalışıyorum (sadece Fransızca ve / veya İspanyolca karakterler). Csvreader ( http://docs.python.org/library/csv.html ) için Python 2.5 belgelerine dayanarak , csvreader yalnızca ASCII'yi desteklediğinden, CSV dosyasını okumak için aşağıdaki kodu buldum.

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:
        ...

Aşağıda okumaya çalıştığım CSV dosyasının bir özeti var:

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
...

UTF-8'e kodlamayı / kod çözmeyi denememe rağmen, hala aşağıdaki istisnayı alıyorum:

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)

Bunu nasıl düzeltirim?


Martin, eğer buralarda olsaydın, kabul edilen yanıtı Martelli'nin Python 2 yanıtından değiştirmeyi düşünür müsün?
— Antti Haapala

Yanıtlar:


114

.encodeYöntem, bir bayt dize yapmak için bir Unicode dize uygulanan alır; ama siz onu bir bayt dizgisiyle çağırıyorsunuz ... yanlış yoldan 'yuvarlak! Bak codecsstandart kütüphanede modül ve codecs.openUTF-8 kodlanmış metin dosyaları okumak için daha iyi genel çözümler için özellikle. Bununla birlikte, csvözellikle modül için, utf-8 verilerini iletmeniz gerekir ve zaten aldığınız şey budur, böylece kodunuz çok daha basit olabilir:

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 

Not: Giriş verilerinizin utf-8'de OLMADIĞI, ancak örneğin ISO-8859-1'de olmadığı ortaya çıkarsa, o zaman bir "kod dönüştürmeye" ihtiyacınız vardır ( csvmodül düzeyinde utf-8 kullanmak istiyorsanız ) , formun line.decode('whateverweirdcodec').encode('utf-8')- ama muhtemelen , ISO-8859- * kodlanmış bytestrings ile gerçekten iyi olacağı gibi , yieldyukarıdaki kodumdaki satırda sadece mevcut kodlamanızın adını kullanabilirsiniz .'utf-8'csv


4
Bu, python belgelerindeki (OP kopyalayıp yapıştırılan yer) örneğin yanlış olduğu anlamına mı geliyor? Unicode csv verdiğinizde kırılırsa yaptığı ekstra kodlama adımının anlamı nedir?
— Anentropik


85

Python 2.X

Sorunlarınızı çözmesi gereken bir unicode-csv kitaplığı vardır, ayrıca csv ile ilgili herhangi bir yeni kod yazmaya gerek yoktur.

İşte benioku dosyalarından bir örnek:

>>> 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

Python 3'te bu, yerleşik csvmodül tarafından kutunun dışında desteklenir . Bu örneğe bakın:

import csv
with open('some.csv', newline='', encoding='utf-8') as f:
    reader = csv.reader(f)
    for row in reader:
        print(row)

11

Utf-8 kodlamalı bir CSV Dosyası okumak istiyorsanız, size önerdiğim minimalist bir yaklaşım şuna benzer bir şey kullanmanızdır:

with open(file_name, encoding="utf8") as csv_file:

Bu ifadeyle, daha sonra çalışmak için bir CSV okuyucu kullanabilirsiniz.


2
Bunun yalnızca Python 3 olması mümkün mü? It kabul etmez Python 2. benim için başarısız encodingiçindeopen
— Zvika

@Zvika evet, python 3'te bu çözüm çalışıyor:open('file.csv', 'r', encoding="ISO8859")
— luca76

Ayrıca open (file_name, "rt", encoding = 'utf-8'), yani dosyayı "metin oku" modunda aç
— Jimmy Lee Jones

3

Ayrıca bu gönderideki yanıtı kontrol edin: https://stackoverflow.com/a/9347871/1338557

Ucsv.py adlı kitaplığın kullanılmasını önerir. Python 2.7 için kodlama problemini (utf-8) ele almak için yazılmış CSV'nin kısa ve basit değişimi. Ayrıca csv.DictReader için destek sağlar

Düzenleme : Kullandığım örnek kodu ekleme:

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'])})

Eğer bağlantı bozuk gider ihtimale karşı Cevabınız o bağlantının bazı ayrıntıları koymalıyız \
— Yaje

# Downvoter- Neden işe yaramayacağını düşündüğünüzden emin değilim. Ucsv kitaplığı benim için gayet iyi çalıştı. 2 günden beri uğraştığım unicde hatasını çözmeye yardımcı oldum. Örnek bir kod arıyorsanız, burada düzenleme @ Yaje'ye gider - Bazı ayrıntıları verdim; ayrıca örnek kod. Ve bağlantı da düzeltildi, bu daha önce başka bir gönderiye işaret ediyordu.
— Atripavan

Bir metin dosyasını ikili olarak açmanızın belirli bir nedeni var mı? 'rb' ikili dosyaları açmak içindir.
— Codeguy007

2

Kullanılması codecs.openAlex Martelli bana faydası olduğu kanıtlanmıştır önerdi olarak.

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 ...

3
Tüm CSV'lerle çalışmaz, aşağıdaki geçerli bir csv satırıdır: "Foo Bar; Baz"; 231; 313; ";;;"; 1;
— jb.

csvModülü içe aktarırsınız ancak kullanmazsınız.
— Christophe Roussy

1

Yardım sayfasına bağlantı python 2.6 için aynı ve bildiğim kadarıyla 2.5'ten beri csv modülünde bir değişiklik olmadı (hata düzeltmelerinin yanı sıra). Burada herhangi bir kodlama / kod çözme olmadan çalışan kod yer almaktadır (da.csv dosyası değişken verilerle aynı verileri içerir ). Dosyanızın herhangi bir dönüştürme olmadan doğru okunması gerektiğini varsayıyorum.

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

Acaba bu hangi python sürümünde çalışır? Hem 2.7 hem de 3.5 ile hata alıyorum. "ValueError: açmak için yeterli değerler (3 beklenen, var 1)"
— eis

@eis: Sisteminizde virgülün varsayılan bir sınırlayıcı olmadığını tahmin edebiliyorum. delimiter=','Bunun yerine eklemeyi deneyin dialect=csv.excel.
— minibüs

1

Sizin için hiçbir şey işe yaramadıysa, yolunuzdan kaçmayı unutmuş olabilirsiniz.
Örneğin, bu kod:

f = open("C:\Some\Path\To\file.csv")

Bir hatayla sonuçlanır:

SyntaxError: (unicode hatası) 'unicodeescape' codec bileşeni 2-3 konumundaki baytların kodunu çözemiyor: kesilmiş \ UXXXXXXXX kaçış

Düzeltmek için şunları yapmanız yeterlidir:

f = open("C:\\Some\\Path\\To\\file.csv")

0

Latin-1Unicode tablosuna baktığımda, 00E9" AKUT LATİN KÜÇÜK E HARFİ " karakter kodunu görüyorum . Bu, örnek verilerinizdeki vurgulu karakterdir. Basit bir test, bu karakter için kodlamanın unicode (neredeyse ) kodlamasından farklı Pythonolduğunu gösterir .UTF-8UTF-16

>>> u'\u00e9'
u'\xe9'
>>> u'\u00e9'.encode('utf-8')
'\xc3\xa9'
>>> 

encode("UTF-8")Özel çağırmadan önce unicode verilerini denemenizi öneririm unicode_csv_reader(). Bir dosyadaki verileri basitçe okumak, kodlamayı gizleyebilir, bu nedenle gerçek karakter değerlerini kontrol edin.


0

Aynı sorunu başka bir sunucuda yaşadım, ancak yerel ayarların karışık olduğunu fark etti.

export LC_ALL="en_US.UTF-8"

sorunu çözdü

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.