I'm overriding the csv.Dictreader.fieldnames property like the following to read all headers from csv files without white space and in lower case.
import csv
class MyDictReader(csv.DictReader):
@property
def fieldnames(self):
return [field.strip().lower() for field in super(MyDictReader, self).fieldnames]
Now my question is, how can I access the fieldnames with automatically strip() and lower() the query?
This is, how I do it manually:
csvDict = MyDictReader(open('csv-file.csv', 'rU'))
for lineDict in csvDict:
query = ' Column_A'.strip().lower()
print(lineDict[query])
Any ideas?
Martijn Pieters
1.1m326 gold badges4.2k silver badges3.5k bronze badges
asked Oct 18, 2012 at 14:26
user1251007
17k14 gold badges52 silver badges78 bronze badges
2 Answers 2
Based on Pedro Romano's suggestion I coded the following example.
import csv
class DictReaderInsensitive(csv.DictReader):
# This class overrides the csv.fieldnames property.
# All fieldnames are without white space and in lower case
@property
def fieldnames(self):
return [field.strip().lower() for field in super(DictReaderInsensitive, self).fieldnames]
def __next__(self):
# get the result from the original __next__, but store it in DictInsensitive
dInsensitive = DictInsensitive()
dOriginal = super(DictReaderInsensitive, self).__next__()
# store all pairs from the old dict in the new, custom one
for key, value in dOriginal.items():
dInsensitive[key] = value
return dInsensitive
class DictInsensitive(dict):
# This class overrides the __getitem__ method to automatically strip() and lower() the input key
def __getitem__(self, key):
return dict.__getitem__(self, key.strip().lower())
For a file containing headers like
- "column_A"
- " column_A"
- "Column_A"
- " Column_A"
- ...
you can access the columns like this:
csvDict = DictReaderInsensitive(open('csv-file.csv', 'rU'))
for lineDict in csvDict:
print(lineDict[' Column_A']) # or
print(lineDict['Column_A']) # or
print(lineDict[' column_a']) # all returns the same
answered Oct 19, 2012 at 8:42
user1251007
17k14 gold badges52 silver badges78 bronze badges
Sign up to request clarification or add additional context in comments.
3 Comments
PrestonDocks
When I try to run this I get the following error: return [field.strip().lower() for field in super(MyDictReader, self).fieldnames] TypeError: must be type, not classobj
user1251007
@PrestonDocks: I learned from this question that
super behaves different in Python2 and Python3. The code should work with Python3. Did you try that?jlev
The problem is that DictReader is an "old style" class in Python2, and is "new style" in Python3. You can fix this by inheriting from object:
DictReaderInsensitive(csv.DictReader, object ):You'll have to do it in two steps:
- Create your
dictspecialisation with a__getitem__method that applies the.strip().lower()to the itskeyparameter. - Override
__next__on yourMyDictReaderspecialised class to return one of your special dictionaries initialised with the dictionary returned by thecsv.DictReadersuperclass's__next__method.
answered Oct 18, 2012 at 17:41
Pedro Romano
11.2k4 gold badges48 silver badges50 bronze badges
Comments
lang-py