पाइथन के साथ UTF8 CSV फ़ाइल पढ़ना


93

मैं पायथन (केवल फ्रेंच और / या स्पेनिश पात्रों) के साथ उच्चारण पात्रों के साथ एक सीएसवी फ़ाइल पढ़ने की कोशिश कर रहा हूं। Csvreader ( http://docs.python.org/library/csv.html ) के लिए पायथन 2.5 दस्तावेज़ के आधार पर , मैं CSV फ़ाइल को पढ़ने के लिए निम्नलिखित कोड के साथ आया था क्योंकि csvreader केवल 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:
        ...

नीचे 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
...

भले ही मैं UTF-8 को एन्कोड / डिकोड करने की कोशिश करता हूं, फिर भी मुझे निम्नलिखित अपवाद मिल रहे हैं:

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)

मैं यह कैसे तय करुं?


मार्टिन, यदि आप आस-पास हैं, तो क्या आप मार्टेली के पाइथन 2 से स्वीकृत उत्तर को स्विच करने पर विचार करेंगे।
अंती हापला

जवाबों:


113

.encodeविधि एक बाइट-स्ट्रिंग बनाने के लिए एक यूनिकोड स्ट्रिंग के लिए लागू किया जाता है; लेकिन आप इसे बाइट-स्ट्रिंग के बजाय बुला रहे हैं ... गलत तरीका 'दौर! को देखो codecsमानक पुस्तकालय में मॉड्यूल और codecs.openUTF-8 एन्कोडेड पाठ फ़ाइलों को पढ़ने के लिए बेहतर सामान्य समाधान के लिए विशेष रूप से। हालाँकि, csvविशेष रूप से मॉड्यूल के लिए , आपको utf-8 डेटा में पास होने की आवश्यकता है, और यह वही है जो आप पहले से प्राप्त कर रहे हैं, इसलिए आपका कोड बहुत सरल हो सकता है:

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 

पुनश्च: यदि यह पता चलता है कि आपका इनपुट डेटा utf-8 में नहीं है, लेकिन उदाहरण के लिए ISO-8859-1 में, तो आपको एक "ट्रांसकोडिंग" की आवश्यकता है (यदि आप csvमॉड्यूल स्तर पर utf-8 का उपयोग करने के इच्छुक हैं ) रूप में line.decode('whateverweirdcodec').encode('utf-8')- लेकिन शायद आप yieldइसके बजाय मेरे कोड में लाइन में अपने मौजूदा एन्कोडिंग के नाम का उपयोग कर सकते हैं 'utf-8', जैसा csvकि वास्तव में आईएसओ-8859- * एनकोडेड बाइट्स के साथ बस ठीक होने जा रहा है।


4
इसका मतलब यह है कि अजगर डॉक्स (जहां ओपी कॉपी और पेस्ट किया गया) में उदाहरण गलत है? यदि आप इसे एक यूनिकोड सीएसवी देते हैं तो यह टूटने पर अतिरिक्त एन्कोडिंग कदम का क्या मतलब है?
एंथ्रोपिक


80

अजगर 2.X

एक यूनिकोड-सीएसवी लाइब्रेरी है जो आपकी समस्याओं को हल करना चाहिए, जिसमें कोई भी नया सीएसवी-संबंधित कोड लिखने के लिए नेविगेट न करने का अतिरिक्त लाभ है।

यहाँ उनके 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]
é ñ

अजगर 3.X

अजगर 3 में यह बॉक्स से बाहर निर्मित csvमॉड्यूल द्वारा समर्थित है । इस उदाहरण को देखें:

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

8

यदि आप एक utv-8 एन्कोडिंग के साथ CSV फ़ाइल पढ़ना चाहते हैं, तो एक न्यूनतम दृष्टिकोण जो मैं आपको सुझाता हूं, वह है:

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

उस कथन के साथ, आप बाद में काम करने के लिए एक सीएसवी रीडर का उपयोग कर सकते हैं।


2
क्या यह संभव है कि यह पायथन 3 ही हो? यह मेरे लिए विफल रहता है, अजगर 2 में यह स्वीकार नहीं करता है encodingमेंopen
Zvika

@Zvika हाँ, अजगर 3 में यह समाधान काम करता है:open('file.csv', 'r', encoding="ISO8859")
luca76

मैं ओपन (file_name, "rt", एन्कोडिंग = 'utf-8') भी जोड़ूंगा, यानी "रीड टेक्स्ट" मोड में खुली फाइल
जिमी ली जोन्स

3

इस पोस्ट में उत्तर की जाँच भी करें: https://stackoverflow.com/a/9347871/1338557

यह ucsv.py नामक पुस्तकालय के उपयोग का सुझाव देता है। CSV के लिए लघु और सरल प्रतिस्थापन पायथन 2.7 के लिए एन्कोडिंग समस्या (utf-8) को संबोधित करने के लिए लिखा गया है। Csv.DictReader के लिए भी समर्थन प्रदान करता है

संपादित करें : नमूना कोड जो मैंने उपयोग किया है:

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

आपको अपने उत्तर में उस लिंक का कुछ विवरण रखना चाहिए, बस लिंक के टूट जाने की स्थिति में
यजी जूल

# डाउनवॉटर- यकीन नहीं होता कि आपने इसका कोई फायदा क्यों नहीं सोचा। Ucsv लाइब्रेरी ने मेरे लिए ठीक काम किया। 2 दिनों से जिस संघर्ष से मैं जूझ रहा था, उसे सुलझाने में मदद की। अगर आप कुछ सैंपल कोड की तलाश में थे, तो यहां एडिट @ यज़ी- में जाता है- मैंने कुछ विवरण दिए हैं; नमूना कोड भी। और लिंक को भी ठीक किया, जो पहले किसी और पोस्ट की ओर इशारा कर रहा था।
अत्रिपावन

किसी विशेष कारण से आप बाइनरी के रूप में एक टेक्स्ट फ़ाइल खोल रहे हैं? 'आरबी' बाइनरी फाइलें खोलने के लिए है।
कोडगुवाई 007

2

का प्रयोग codecs.openके रूप में एलेक्स मार्टेली मेरे लिए उपयोगी साबित हुई सुझाव दिया।

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
यह सभी सीएसवी के साथ काम नहीं करेगा, निम्नलिखित एक वैध सीएसवी पंक्ति है: "फू बार; बाज"; 231; 313; ";;;"; 1;
जेबी

आप csvमॉड्यूल आयात करते हैं लेकिन इसका उपयोग नहीं करते हैं।
क्रिस्टोफ रूसो

1

हेल्प पेज का लिंक पायथन 2.6 के लिए समान है और जहाँ तक मुझे पता है कि 2.5 (बग फिक्स के अलावा) सीएसवी मॉड्यूल में कोई बदलाव नहीं हुआ था। यहां वह कोड है जो बिना किसी एन्कोडिंग / डिकोडिंग के काम करता है (फ़ाइल da.csv में वैरिएबल डेटा के समान डेटा है )। मैं मानता हूं कि आपकी फ़ाइल को बिना किसी रूपांतरण के सही ढंग से पढ़ा जाना चाहिए।

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

मुझे आश्चर्य है कि अजगर के किस संस्करण में यह काम करेगा? मुझे २. get और ३.५ दोनों के साथ त्रुटियां हैं। "ValueError: अनपैक करने के लिए पर्याप्त मान नहीं (अपेक्षित 3, 1 मिला)"
eis

@ आईस: मैं कल्पना कर सकता हूं कि आपके सिस्टम पर अल्पविराम डिफ़ॉल्ट सीमांकक नहीं है। के delimiter=','बजाय जोड़ने की कोशिश करें dialect=csv.excel
वैन

1

ध्यान देने योग्य बात यह है कि यदि आपके लिए कुछ भी काम नहीं किया गया है, तो आप अपने रास्ते से बचना भूल सकते हैं।
उदाहरण के लिए, यह कोड:

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

परिणाम में त्रुटि होगी:

SyntaxError: (यूनिकोड त्रुटि) 'यूनिकोडेसस्केप' कोडक 2-3 में बाइट्स को डिकोड नहीं कर सकता है: काट दिया गया \ UXXXXXXXX बच

ठीक करने के लिए, बस करें:

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

0

को देखते हुए Latin-1यूनिकोड तालिका , मैं चरित्र कोड देखें 00E9" लैटिन छोटे अक्षर ई के साथ तीव्र "। यह आपके नमूना डेटा में उच्चारण चरित्र है। एक सरल परीक्षण से Pythonपता चलता है कि UTF-8इस चरित्र के लिए एन्कोडिंग यूनिकोड (लगभग UTF-16) एन्कोडिंग से अलग है ।

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

मेरा सुझाव है कि आप encode("UTF-8")विशेष कॉल करने से पहले यूनिकोड डेटा का प्रयास करें unicode_csv_reader()। बस फ़ाइल से डेटा पढ़ना एन्कोडिंग को छिपा सकता है, इसलिए वास्तविक चरित्र मान जांचें।


0

एक अन्य सर्वर पर एक ही समस्या थी, लेकिन एहसास हुआ कि स्थान गड़बड़ हैं।

export LC_ALL="en_US.UTF-8"

समस्या को ठीक किया

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.