Though you already have an accepted answer, I figured I'd add this for anyone else interested in a different solution-
- The
csvmodule'sDictReaderobject has a public attribute calledfieldnames(as of Python 2.6 and above). https://docs.python.org/3.4/library/csv.html#csv.csvreader.fieldnames
An implementation could be as follows:
import csv
with open('C:/mypath/to/csvfile.csv', 'r') as f:
dict_reader = csv.DictReader(f)
#get header fieldnames from DictReader and store in list
headers = dict_reader.fieldnames
#sample file reading logic
for line in dict_reader:
print(line[headers[0]])
In the above, dict_reader.fieldnames returns a list of your headers (assuming the headers are in the top row). Which allows...
>>> print(headers)
['MyColumn1', 'MyColumn2', 'MyColumn3']
If your headers are in, say the 2nd row (with the very top row being row 1), you could do as follows:
import csv
with open('C:/mypath/to/csvfile.csv', 'r') as f:
#you can eat the first line before creating DictReader.
#if no "fieldnames" param is passed into
#DictReader object upon creation, DictReader
#will read the upper-most line as the headers
f.readline()
dict_reader = csv.DictReader(f)
headers = dict_reader.fieldnames
#sample file reading logic
for line in dict_reader:
print(line[headers[0]])
Answer from user3194712 on Stack OverflowThough you already have an accepted answer, I figured I'd add this for anyone else interested in a different solution-
- The
csvmodule'sDictReaderobject has a public attribute calledfieldnames(as of Python 2.6 and above). https://docs.python.org/3.4/library/csv.html#csv.csvreader.fieldnames
An implementation could be as follows:
import csv
with open('C:/mypath/to/csvfile.csv', 'r') as f:
dict_reader = csv.DictReader(f)
#get header fieldnames from DictReader and store in list
headers = dict_reader.fieldnames
#sample file reading logic
for line in dict_reader:
print(line[headers[0]])
In the above, dict_reader.fieldnames returns a list of your headers (assuming the headers are in the top row). Which allows...
>>> print(headers)
['MyColumn1', 'MyColumn2', 'MyColumn3']
If your headers are in, say the 2nd row (with the very top row being row 1), you could do as follows:
import csv
with open('C:/mypath/to/csvfile.csv', 'r') as f:
#you can eat the first line before creating DictReader.
#if no "fieldnames" param is passed into
#DictReader object upon creation, DictReader
#will read the upper-most line as the headers
f.readline()
dict_reader = csv.DictReader(f)
headers = dict_reader.fieldnames
#sample file reading logic
for line in dict_reader:
print(line[headers[0]])
You can read the header by using the next() function which return the next row of the reader’s iterable object as a list. then you can add the content of the file to a list.
import csv
with open("C:/path/to/.filecsv", "rb") as f:
reader = csv.reader(f)
i = reader.next()
rest = list(reader)
Now i has the column's names as a list.
print i
>>>['id', 'name', 'age', 'sex']
Also note that reader.next() does not work in python 3. Instead use the the inbuilt next() to get the first line of the csv immediately after reading like so:
import csv
with open("C:/path/to/.filecsv", "rb") as f:
reader = csv.reader(f)
i = next(reader)
print(i)
>>>['id', 'name', 'age', 'sex']
python - How to write header row with csv.DictWriter? - Stack Overflow
Python csv DictReader with optional header - Stack Overflow
python csv headers - Stack Overflow
How Can I Check if a CSV File has Headers
Edit:
In 2.7 / 3.2 there is a new writeheader() method. Also, John Machin's answer provides a simpler method of writing the header row.
Simple example of using the writeheader() method now available in 2.7 / 3.2:
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
Instantiating DictWriter requires a fieldnames argument.
From the documentation:
The fieldnames parameter identifies the order in which values in the dictionary passed to the writerow() method are written to the csvfile.
Put another way: The Fieldnames argument is required because Python dicts are inherently unordered.
Below is an example of how you'd write the header and data to a file.
Note: with statement was added in 2.6. If using 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)
As @FM mentions in a comment, you can condense header-writing to a one-liner, e.g.:
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)
A few options:
(1) Laboriously make an identity-mapping (i.e. do-nothing) dict out of your fieldnames so that csv.DictWriter can convert it back to a list and pass it to a csv.writer instance.
(2) The documentation mentions "the underlying writer instance" ... so just use it (example at the end).
dw.writer.writerow(dw.fieldnames)
(3) Avoid the csv.Dictwriter overhead and do it yourself with csv.writer
Writing data:
w.writerow([d[k] for k in fieldnames])
or
w.writerow([d.get(k, restval) for k in fieldnames])
Instead of the extrasaction "functionality", I'd prefer to code it myself; that way you can report ALL "extras" with the keys and values, not just the first extra key. What is a real nuisance with DictWriter is that if you've verified the keys yourself as each dict was being built, you need to remember to use extrasaction='ignore' otherwise it's going to SLOWLY (fieldnames is a list) repeat the check:
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'
>>>
You may be able to use a csv.Sniffer here.
The has_header method peeks at the data and uses heuristics to determine whether a header is present (refer to the doc for the exact logic).
Note that in the example data shown in the question, the sniffer heuristic would incorrectly consider both headerless and headerful to have a header. That's probably a consequence of your sample data having only a single row, if I add a second numeric row 4,5,6 in the input data then the Sniffer.has_header method works as expected.
A basic implementation which assumes csvfile is seekable could look like this:
def print_data_rows(csvfile):
reader = csv.DictReader(csvfile, fieldnames=FIELDNAMES)
sniffer = csv.Sniffer()
sample = csvfile.read(1024)
csvfile.seek(0)
if sniffer.has_header(sample):
next(reader)
for row in reader:
print(row)
It's easy to adapt if your stream isn't seekable, just buffer the first line.
You can implement the custom behavior by overriding csv.DictReader.__next__ such that it would read another row if the first row is the same as the given field names:
class HeaderOptionalDictReader(csv.DictReader):
def __init__(self, *args, fieldnames=None, **kwargs):
super().__init__(*args, fieldnames=fieldnames, **kwargs)
self.skip_header = fieldnames is not None
def __next__(self):
row = super().__next__()
if self.skip_header and list(row.values()) == self.fieldnames:
row = super().__next__()
self.skip_header = False
return row
Demo: https://ideone.com/eYbiZg
Based on your edit, you need to skip the initial space after the comma.
This should do it:
>>> reader = csv.DictReader(open(PathFile),skipinitialspace=True)
I am not exactly sure what you want to achieve but if you simply want to know if some columns is in CSV, and you are sure that all rows have same columns, and you want to use dict reader use this
s="""col1,col2,col3
ok,ok,ok
hmm,hmm,hmm
cool,cool,cool"""
import csv
reader = csv.DictReader(s.split("\n"))
print reader.fieldnames
for row in reader:
for colName in ['col3', 'col4']:
print "found %s %s"%(colName, colName in row)
break
It outputs
found col3 True
found col4 False
or something like this will work too
reader = csv.reader(s.split("\n"))
columns = reader.next()
for colName in ['col3', 'col4']:
print "found %s %s"%(colName, colName in columns)