2011-04-30 12 views
41
  1. मेरे पास यूनिकोड स्ट्रिंग वाले शब्दकोशों की एक सूची है।
  2. csv.DictWriter सीएसवी फ़ाइल में शब्दकोशों की एक सूची लिख सकता है।
  3. मैं चाहता हूं कि सीएसवी फ़ाइल को यूटीएफ 8 में एन्कोड किया जाए।
  4. csv मॉड्यूल यूनिकोड तारों को यूटीएफ 8 में परिवर्तित करने में संभाल नहीं सकता है।

    पायथन डिक्टवाइटर लेखन यूटीएफ -8 एन्कोडेड सीएसवी फाइल

    def utf_8_encoder(unicode_csv_data): 
        for line in unicode_csv_data: 
         yield line.encode('utf-8') 
    
  5. यह भी एक UnicodeWriter वर्ग है:

  6. csv मॉड्यूल प्रलेखन UTF8 के लिए सब कुछ परिवर्तित करने के लिए एक उदाहरण है।

लेकिन ... मैं DictWriter इनके साथ कैसे काम करूं? क्या उन्हें अलग-अलग शब्दकोशों को पकड़ने और उन्हें फ़ाइल में लिखने से पहले उन्हें एन्कोड करने के लिए अपने बीच में इंजेक्ट नहीं करना पड़ेगा? मुझे यह नहीं मिला।

उत्तर

71

अगर पायथन 2.7 का उपयोग कर या बाद में, DictWriter को पार करने से पहले utf-8 के लिए शब्दकोश पुन: मैप करने के लिए एक dict समझ का उपयोग करें:

# coding: utf-8 
import csv 
D = {'name':u'马克','pinyin':u'mǎkè'} 
f = open('out.csv','wb') 
f.write(u'\ufeff'.encode('utf8')) # BOM (optional...Excel needs it to open UTF-8 file properly) 
w = csv.DictWriter(f,sorted(D.keys())) 
w.writeheader() 
w.writerow({k:v.encode('utf8') for k,v in D.items()}) 
f.close() 

आप DictUnicodeWriter को UnicodeWriter अद्यतन करने के लिए इस विचार का उपयोग कर सकते हैं:

# coding: utf-8 
import csv 
import cStringIO 
import codecs 

class DictUnicodeWriter(object): 

    def __init__(self, f, fieldnames, dialect=csv.excel, encoding="utf-8", **kwds): 
     # Redirect output to a queue 
     self.queue = cStringIO.StringIO() 
     self.writer = csv.DictWriter(self.queue, fieldnames, dialect=dialect, **kwds) 
     self.stream = f 
     self.encoder = codecs.getincrementalencoder(encoding)() 

    def writerow(self, D): 
     self.writer.writerow({k:v.encode("utf-8") for k,v in D.items()}) 
     # Fetch UTF-8 output from the queue ... 
     data = self.queue.getvalue() 
     data = data.decode("utf-8") 
     # ... and reencode it into the target encoding 
     data = self.encoder.encode(data) 
     # write to the target stream 
     self.stream.write(data) 
     # empty queue 
     self.queue.truncate(0) 

    def writerows(self, rows): 
     for D in rows: 
      self.writerow(D) 

    def writeheader(self): 
     self.writer.writeheader() 

D1 = {'name':u'马克','pinyin':u'Mǎkè'} 
D2 = {'name':u'美国','pinyin':u'Měiguó'} 
f = open('out.csv','wb') 
f.write(u'\ufeff'.encode('utf8')) # BOM (optional...Excel needs it to open UTF-8 file properly) 
w = DictUnicodeWriter(f,sorted(D.keys())) 
w.writeheader() 
w.writerows([D1,D2]) 
f.close() 
+0

मैंने सोचा कि पायथन (x, y) 2.6.6.0 में डाउनग्रेड करना चीजों को आसान बना देगा। :) – endolith

+9

@endolith: आप 'dict (v, v.encode ('utf-8') का उपयोग कर सकते हैं यदि isinstance (v, यूनिकोड) अन्य v) के लिए v, v.iteritems() में v) v के बजाए पायथन 2.6 पर समझ। – jfs

+4

'अगर आईएसआईइंस्टेंस (वी, यूनिकोड)' हिस्सा आवश्यक है! – reubano

2

जब आप अपनी सामग्री के साथ csv.writer पर कॉल करते हैं, तो विचार utf_8_encoder के माध्यम से सामग्री को पास करना है क्योंकि यह आपको (utf-8) एन्कोडेड सामग्री प्रदान करेगा।

6

आप dict मूल्यों के रूप में की जरूरत एन्कोड करने के लिए इस तरह की कुछ प्रॉक्सी वर्ग का उपयोग कर सकते हैं:

# -*- coding: utf-8 -*- 
import csv 
d = {'a':123,'b':456, 'c':u'Non-ASCII: проверка'} 

class DictUnicodeProxy(object): 
    def __init__(self, d): 
     self.d = d 
    def __iter__(self): 
     return self.d.__iter__() 
    def get(self, item, default=None): 
     i = self.d.get(item, default) 
     if isinstance(i, unicode): 
      return i.encode('utf-8') 
     return i 

with open('some.csv', 'wb') as f: 
    writer = csv.DictWriter(f, ['a', 'b', 'c']) 
    writer.writerow(DictUnicodeProxy(d)) 
14

आप तेज़ी से UTF-8 में मूल्यों में बदल सकते हैं जैसा कि आप DictWriter.writerow() को dict गुजरती हैं।

import csv 

rows = [ 
    {'name': u'Anton\xedn Dvo\u0159\xe1k','country': u'\u010cesko'}, 
    {'name': u'Bj\xf6rk Gu\xf0mundsd\xf3ttir', 'country': u'\xcdsland'}, 
    {'name': u'S\xf8ren Kierkeg\xe5rd', 'country': u'Danmark'} 
    ] 

# implement this wrapper on 2.6 or lower if you need to output a header 
class DictWriterEx(csv.DictWriter): 
    def writeheader(self): 
     header = dict(zip(self.fieldnames, self.fieldnames)) 
     self.writerow(header) 

out = open('foo.csv', 'wb') 
writer = DictWriterEx(out, fieldnames=['name','country']) 
# DictWriter.writeheader() was added in 2.7 (use class above for <= 2.6) 
writer.writeheader() 
for row in rows: 
    writer.writerow(dict((k, v.encode('utf-8')) for k, v in row.iteritems())) 
out.close() 

आउटपुट foo.csv: उदाहरण के लिए:

name,country 
Antonín Dvořák,Česko 
Björk Guðmundsdóttir,Ísland 
Søren Kierkegård,Danmark 
+0

अच्छा एक। मुझे एक लाइनर लेखको func के कार्यान्वयन पसंद आया। – shahjapan

+6

'writer.writerow (dict ((k, v.encode ('utf-8') यदि टाइप (v) यूनिकोड है v) v के लिए v। V। V। V में v। V)। केवल यूनिकोड के लिए एन्कोड वर्ण। क्योंकि int/सूची में यूनिकोड विशेषता नहीं है। –

1

मेरा समाधान थोड़ा अलग है। हालांकि उपर्युक्त सभी समाधान यूनिकोड संगत निर्देश रखने पर ध्यान केंद्रित कर रहे हैं, मेरे समाधान डिक्टवाइटर को यूनिकोड के साथ संगत बनाता है। पाइथन डॉक्स (1) में यह दृष्टिकोण भी सुझाया गया है।

कक्षाएं UTF8Recoder, यूनिकोड रीडर, यूनिकोडवाइटर पाइथन दस्तावेज़ से लिया जाता है। यूनिकोडवाइटर-> लेखक को थोड़ा सा बदल दिया गया था।

इसे नियमित डिक्टवाइटर/डिक्ट्रेडर के रूप में उपयोग करें। एक सरल अद्भुत UnicodeCSV मॉड्यूल का उपयोग कर वैकल्पिक हल नहीं है

import csv, codecs, cStringIO 

class UTF8Recoder: 
    """ 
    Iterator that reads an encoded stream and reencodes the input to UTF-8 
    """ 
    def __init__(self, f, encoding): 
     self.reader = codecs.getreader(encoding)(f) 

    def __iter__(self): 
     return self 

    def next(self): 
     return self.reader.next().encode("utf-8") 

class UnicodeReader: 
    """ 
    A CSV reader which will iterate over lines in the CSV file "f", 
    which is encoded in the given encoding. 
    """ 

    def __init__(self, f, dialect=csv.excel, encoding="utf-8", **kwds): 
     f = UTF8Recoder(f, encoding) 
     self.reader = csv.reader(f, dialect=dialect, **kwds) 

    def next(self): 
     row = self.reader.next() 
     return [unicode(s, "utf-8") for s in row] 

    def __iter__(self): 
     return self 

class UnicodeWriter: 
    """ 
    A CSV writer which will write rows to CSV file "f", 
    which is encoded in the given encoding. 
    """ 

    def __init__(self, f, dialect=csv.excel, encoding="utf-8", **kwds): 
     # Redirect output to a queue 
     self.queue = cStringIO.StringIO() 
     self.writer = csv.writer(self.queue, dialect=dialect, **kwds) 
     self.stream = f 
     self.encoder = codecs.getincrementalencoder(encoding)() 

    def writerow(self, row): 
     self.writer.writerow([unicode(s).encode("utf-8") for s in row]) 
     # Fetch UTF-8 output from the queue ... 
     data = self.queue.getvalue() 
     data = data.decode("utf-8") 
     # ... and reencode it into the target encoding 
     data = self.encoder.encode(data) 
     # write to the target stream 
     self.stream.write(data) 
     # empty queue 
     self.queue.truncate(0) 

    def writerows(self, rows): 
     for row in rows: 
      self.writerow(row) 

class UnicodeDictWriter(csv.DictWriter, object): 
    def __init__(self, f, fieldnames, restval="", extrasaction="raise", dialect="excel", *args, **kwds): 
     super(UnicodeDictWriter, self).__init__(f, fieldnames, restval="", extrasaction="raise", dialect="excel", *args, **kwds) 
     self.writer = UnicodeWriter(f, dialect, **kwds) 
31

:

यहाँ कोड है।यह होने के बाद, बस लाइन

import csv 

बदलने

import unicodecsv as csv 

करने और यह पूर्ण रूप से अपने UTF-8 के साथ अच्छा खेल रहा शुरू होता है।

नोट: अजगर 3 पर स्विच किया जा भी इस समस्या (टिप के लिए धन्यवाद jamescampbell) की आप छुटकारा होगा। और यह वैसे भी कुछ करना चाहिए।

+4

ओएमएफजी अंत में - यह –

+3

तक यह एक दुःस्वप्न क्या रहा है यह स्वीकार्य उत्तर होना चाहिए - इतना आसान और एक आकर्षण की तरह काम करता है –

+1

अब आपको Python 3.x – jamescampbell

संबंधित मुद्दे