Reputation: 1496
I have this Python code:
import csv
csvfile = 'stations-nl-2014-01.csv'
try:
f = open(csvfile, 'r')
reader = csv.DictReader(f, delimiter=';')
for row in reader:
print(row['name'], '--', row['type'])
finally:
f.close()
I can use the regular csv.reader() method, but I was told using csv.DictReader() is best practise because you can select columns by their names which makes the code more readable. However, when I use the normal csv.reader() method, no error is shown. When I use DictReader, I get the following error:
print(row['name'], '--', row['type'])
KeyError: 'name'
When I change my code to:
import csv
csvfile = 'stations-nl-2014-01.csv'
try:
f = open(csvfile, 'r')
reader = csv.reader(f, delimiter=';')
for row in reader:
print(row)
finally:
f.close()
...everything works fine. But using csv.DictReader() and selecting rows by their column names raises the error. Anyone know how to fix this? I've double checked the path of the .csv file and the column names and it's all correct (works fine without DictReader).
Upvotes: 0
Views: 21144
Reputation: 2963
Late answer, srooy.
The problem is pretty trivial. I just had it, came here because I was in doubt, but I was already suspecting what the cause was. It took me a minute two figure it out, but as I see that nobody actually answered it, I will do that to save somebody some work.
In short, this is my code (it' s the real thing, it's a silly example I was working on). This is the CSV:
name,surname
Manuel,van der Heide
Pedro-Paco,Bulebú Dancé-Avecmuâ
Dietrich, von dem Bach-Schleußenhübner zu Jägerstein
Jan, ter Kraale
Robert-Jan, Fietsema
François, le Felpudin
Manon, van Brummen
Menno, 't Hof
Alfonso, Décimo Elsabio
Karl-Heinz, von Bubbler
Carlos, Pi García
Luise, Klaver-Hover
Joao, da Silva Fernandes do Pinhal
The names are just stupid ones I made up for testing variations of surnames.
And this is the pretty silly script. I was only using it to check how it looked like before starting to work. I want to try a few things to generate meaningful login names, but that is not relevant here. So of completeness's sake here it is:
#! /usr/bin/python3
import argparse,csv
# Create the parser
parser = argparse.ArgumentParser()
parser.add_argument('-f','--file')
args = parser.parse_args()
csv_input = args.file
# print(args.file.readlines())
with open(csv_input, mode='r') as csvito:
csv_reader = csv.DictReader(csvito)
line_count = 0
for row in csv_reader:
if line_count == 0:
print(f'Column names are {", ".join(row)}')
line_count += 1
print(f'\t{row["name"]} - {row["surname"]}')
line_count += 1
print
Note that the error has nothing to do with the code (well, kinda).
The simple answer:
There are two empty spaces after the last column. That's all
To correct it, just remove the empty spaces, add a comma after the last word.
There may be more elegant solutions (you can use the str.strip() function with Pandas read_csv), but I just wanted to add my quick five cents :)
Upvotes: 1
Reputation: 31445
This is a bad question because nobody knows what is in the CSV file.
However I had the same situation and on the first key I was getting key error.
It turns out that the file, which had been created initially in Excel, was saved with UTF-8 encoding and had a silent '\ufeff'
prefix
My fix was to convert each dict to use ascii-encoded strings
def convert_row( row ):
row_dict = {}
for key, value in row.items():
keyAscii = key.encode('ascii', 'ignore' ).decode()
valueAscii = value.encode('ascii','ignore').decode()
row_dict[ keyAscii ] = valueAscii
return row_dict
This can also be done with map / lambda e.g.
def ascii_encode( str ):
return str.encode( 'ascii', 'ignore' ).decode()
def convert_row( row ):
return dict(map( lambda(key,value) :
(ascii_encode(key),ascii_encode(value) ), row.items() ) )
or something like that
The main issue in my answer is the possible requirement to ascii_encode the strings if the file is utf-8.
Upvotes: 5
Reputation: 61
1) I searched up file 'stations-nl-2014-01.csv' on the web, and I see that it does not have column 'name'. Column 'type' exists though.
It has the following columns: code uic naam middel_naam korte_naam rdt_url type geo_lat geo_lng
Are you sure you shouldn't be looking for row['naam']?
2) If the above doesn't work, you can get a list of keys that your 'row' dictionary contains using row.keys(). This will give you a list of the keys that csv.DictReader actually recognized.
Upvotes: 1