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 Overflowpython - Reading column names alone in a csv file - Stack Overflow
csv.DictReader when one of my fields is a list
python - Replace fieldnames when using DictReader - Stack Overflow
python - Read CSV items with column name - Stack Overflow
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]])
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']
I would like to read a csv into a dict but one of my fields is a list. Like so:
item, num_ordered, people
apple, 4, ['Janet', 'Sam']
grape, 1, ['Stu', 'Jenny']
I used csv.DictReader without the `fieldnames` kwarg so the header row became the names of the keys. But it's picking up the commas in the lists as the end of a field. How do I get it to recognize that these are lists?
The easiest way is to just set:
reader.fieldnames = "email", "name", "id", "phone"
You can save the old fieldnames if you want too.
Just replace this line:
reader = csv.DictReader(f, fieldnames = ( "foo","bar","foobar","barfoo" ))
with this:
reader = csv.DictReader(f, fieldnames=("id", "email", "name", "phone"))
You are looking for DictReader
with open('info.csv') as f:
reader = csv.DictReader(f, delimiter=';')
for row in reader:
name = row['name']
blah = row['blah']
to quote from the link:
Create an object which operates like a regular reader but maps the information read into a dict whose keys are given by the optional fieldnames parameter. ... If the fieldnames parameter is omitted, the values in the first row of the csvfile will be used as the fieldnames.
You can use a csv.DictReader instance to get this behaviour.
Example from the docs:
>>> with open('names.csv', newline='') as csvfile:
... reader = csv.DictReader(csvfile)
... for row in reader:
... print(row['first_name'], row['last_name'])
...
Eric Idle
John Cleese
The reader generates the dictionary keys from the first row of the csv file automatically. If the csv file does not contain a header row you can set the keys by passing a list to the DictReader:
fieldnames = ['first_name', 'last_name']
reader = csv.DictReader(csvfile, fieldnames=fieldnames)
Ok, this will make more sense. Why does this work:
import csv
with open('test.csv') as csv_file:
csv_reader = csv.DictReader(csv_file)
for row in csv_reader:
print(row)But this gives an error that the file is closed:
import csv
with open('test.csv') as csv_file:
csv_reader = csv.DictReader(csv_file)
for row in csv_reader:
print(row)
Traceback (most recent call last): File "c:\Users\John\Documents\Python\test_project\test2.py", line 5, in <module> for row in csv_reader: File "C:\Users\John\AppData\Local\Programs\Python\Python311\Lib\csv.py", line 110, in next self.fieldnames File "C:\Users\John\AppData\Local\Programs\Python\Python311\Lib\csv.py", line 97, in fieldnames self._fieldnames = next(self.reader) ^ ValueError: I/O operation on closed file.
Does DictReader (and also reader) not just run once and return a value? Why is csv_file being accessed after the line it's used in?
Thanks!
I'd say your best bet is to do a simple assert that heading is not None:
try:
with open("inpu.csv", newline="") as f:
reader = csv.DictReader(f, skipinitialspace=True)
headings = reader.fieldnames
assert headings is not None
assert len(headings) == 3
menu: list[list[str]] = []
for row in reader:
menu.append([row[headings[0]], row[headings[1]], row[headings[2]]])
except IOError as e:
print(f"couldn't open CSV: {e}")
except AssertionError:
print(
f"couldn't get fieldnames, check CSV and ensure first line is a properly encoded row"
)
else:
print(menu)
If it fails, you'll know to look at the CSV file for any kind of issues.
- Before the assert, VSCode shows that headings could be
Sequence[str] | None. - After the assert, the type checker realizes that it cannot have been None, so headings must be
Sequence[str].
Also, look at Barmar's and Mark Tolonen's comments, you can do what you much more simply by just reading the CSV as a list of strings:
reader = csv.reader(f)
menu = list(reader)[1:]
print(menu)
[
["foo", "1", "a"],
["bar", "2", "b"],
["baz", "3", "c"],
]
fieldnames can potentially be None if the CSV file is empty.
You can solve your problem by providing a default value.
headings: list[str] = reader.fieldnames or ["", "", ""]