Csv.DictWriter के साथ हेडर पंक्ति कैसे लिखें?


114

मान लें कि मेरे पास एक csv.DictReaderवस्तु है और मैं इसे सीएसवी फ़ाइल के रूप में लिखना चाहता हूं। मैं यह कैसे कर सकता हूँ?

मुझे पता है कि मैं डेटा की पंक्तियों को इस तरह लिख सकता हूं :

dr = csv.DictReader(open(f), delimiter='\t')
# process my dr object
# ...
# write out object
output = csv.DictWriter(open(f2, 'w'), delimiter='\t')
for item in dr:
    output.writerow(item)

लेकिन मैं फील्डनाम कैसे शामिल कर सकता हूं?

जवाबों:


149

संपादित करें:
2.7 / 3.2 में एक नई writeheader()विधि है । इसके अलावा, जॉन माचिन का जवाब हेडर पंक्ति लिखने की एक सरल विधि प्रदान करता है। 2.7 / 3.2 में अब उपलब्ध विधि
का उपयोग करने का सरल उदाहरण writeheader():

from collections import OrderedDict
ordered_fieldnames = OrderedDict([('field1',None),('field2',None)])
with open(outfile,'wb') as fou:
    dw = csv.DictWriter(fou, delimiter='\t', fieldnames=ordered_fieldnames)
    dw.writeheader()
    # continue on to write data

DictWriter को तुरंत शुरू करने के लिए एक फ़ील्ड नाम तर्क की आवश्यकता होती है।
से प्रलेखन :

फ़ील्डनाम पैरामीटर उस क्रम की पहचान करता है जिसमें लेखक को दिए गए शब्दकोष () विधि में मान को csvfile लिखा जाता है।

दूसरा तरीका रखें: फ़ील्डनाम तर्क की आवश्यकता है क्योंकि पायथन डाइक स्वाभाविक रूप से अनियंत्रित हैं।
नीचे एक उदाहरण दिया गया है कि आप किसी फ़ाइल में हेडर और डेटा कैसे लिखेंगे।
नोट: withबयान 2.6 में जोड़ा गया था। यदि 2.5 का उपयोग कर रहे हैं:from __future__ import with_statement

with open(infile,'rb') as fin:
    dr = csv.DictReader(fin, delimiter='\t')

# dr.fieldnames contains values from first row of `f`.
with open(outfile,'wb') as fou:
    dw = csv.DictWriter(fou, delimiter='\t', fieldnames=dr.fieldnames)
    headers = {} 
    for n in dw.fieldnames:
        headers[n] = n
    dw.writerow(headers)
    for row in dr:
        dw.writerow(row)

जैसा कि @FM ने एक टिप्पणी में उल्लेख किया है, आप हेडर-राइटिंग को एक-लाइनर को लिख सकते हैं, जैसे:

with open(outfile,'wb') as fou:
    dw = csv.DictWriter(fou, delimiter='\t', fieldnames=dr.fieldnames)
    dw.writerow(dict((fn,fn) for fn in dr.fieldnames))
    for row in dr:
        dw.writerow(row)

12
+1 फिर भी हेडर लिखने का एक और तरीका dw.writerow( dict((f,f) for f in dr.fieldnames) ):।
FMc

2
@ एडम: एक छोटे लाइनर के लिए, मेरा उत्तर देखें।
जॉन मैकिन

2
@ जॉन: आपके उत्तर के लिए +1; बस "अंतर्निहित लेखक उदाहरण" का उपयोग करना निश्चित रूप से "श्रमसाध्य पहचान-मानचित्रण" के लिए बेहतर है।
यांत्रिक_मीट

1
@endolith: प्रतिक्रिया के लिए धन्यवाद। उत्तर के शीर्ष पर उस हिस्से को ले जाया गया।
यांत्रिक_मीट

1
चूंकि आप एक तानाशाह के रूप में अच्छी तरह से उपयोग कर रहे हैं, तो खेतों को जोड़ना आसान है dw = csv.DictWriter(fou, delimiter='\t', fieldnames=dr.fieldnames)। इस तरह, यदि आपके क्षेत्र बदलते हैं तो आपको तानाशाह को समायोजित करने की आवश्यकता नहीं है।
स्पेंसर रथबुन

29

कुछ विकल्प:

(1) अपने फील्डनामों से श्रमपूर्वक एक पहचान-मानचित्रण (यानी कुछ भी न करें) करें ताकि csv.DictWriter इसे वापस एक सूची में बदल सके और इसे एक csv.writer उदाहरण में पास कर सके।

(2) दस्तावेज़ीकरण में "अंतर्निहित writerउदाहरण" का उल्लेख किया गया है ... इसलिए बस इसका उपयोग करें (उदाहरण के अंत में)।

dw.writer.writerow(dw.fieldnames)

(3) csv.Dictwriter ओवरहेड से बचें और इसे csv.writer के साथ स्वयं करें

लेखन डेटा:

w.writerow([d[k] for k in fieldnames])

या

w.writerow([d.get(k, restval) for k in fieldnames])

extrasaction"कार्यक्षमता" के बजाय , मैं इसे स्वयं कोड करना पसंद करूंगा; इस तरह आप कुंजियों और मूल्यों के साथ सभी "अतिरिक्त" रिपोर्ट कर सकते हैं, न कि केवल पहली अतिरिक्त कुंजी। DictWriter के साथ एक वास्तविक उपद्रव यह है कि यदि आपने कुंजियों को स्वयं सत्यापित कर लिया है कि प्रत्येक ताना बनाया जा रहा है, तो आपको एक्सट्रैक्शन = 'इग्नोर' का उपयोग करने के लिए याद रखने की आवश्यकता है अन्यथा यह धीरे-धीरे जा रहा है (फ़ील्डनाम एक सूची है: चेक को दोहराएं:

wrong_fields = [k for k in rowdict if k not in self.fieldnames]

============

>>> f = open('csvtest.csv', 'wb')
>>> import csv
>>> fns = 'foo bar zot'.split()
>>> dw = csv.DictWriter(f, fns, restval='Huh?')
# dw.writefieldnames(fns) -- no such animal
>>> dw.writerow(fns) # no such luck, it can't imagine what to do with a list
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\python26\lib\csv.py", line 144, in writerow
    return self.writer.writerow(self._dict_to_list(rowdict))
  File "C:\python26\lib\csv.py", line 141, in _dict_to_list
    return [rowdict.get(key, self.restval) for key in self.fieldnames]
AttributeError: 'list' object has no attribute 'get'
>>> dir(dw)
['__doc__', '__init__', '__module__', '_dict_to_list', 'extrasaction', 'fieldnam
es', 'restval', 'writer', 'writerow', 'writerows']
# eureka
>>> dw.writer.writerow(dw.fieldnames)
>>> dw.writerow({'foo':'oof'})
>>> f.close()
>>> open('csvtest.csv', 'rb').read()
'foo,bar,zot\r\noof,Huh?,Huh?\r\n'
>>>

वर्तमान में पायथन 3.6 में, extrasactionकार्यक्षमता बेहतर तरीके से लागू होती है। यह अब wrong_fields = rowdict.keys() - self.fieldnames so it's effectively a सेट है 'ऑपरेशन।
मार्टिउ

मैं इस उत्तर को 'डिक्टवर्टर से बचने' की टिप्पणी के लिए वोट कर रहा हूं - मैंने इसका उपयोग करने के लिए कोई लाभ नहीं देखा है, और अपने डेटा की संरचना और सीएसवी लिखने के लिए तेज लगता है
neophytte

8

ऐसा करने का एक और तरीका यह होगा कि आप अपने आउटपुट में लाइनों को जोड़ने से पहले, निम्न पंक्ति को जोड़ेंगे:

output.writerow(dict(zip(dr.fieldnames, dr.fieldnames)))

ज़िप एक ही मूल्य वाले दोहे की सूची लौटाएगा। इस सूची का इस्तेमाल एक शब्दकोश शुरू करने के लिए किया जा सकता है।

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