# work around python2's csv.py's difficulty with utf8
# partly cribbed from http://stackoverflow.com/questions/5478659/python-module-like-csv-dictreader-with-full-utf8-support

class EmptyCSVError(Exception):
    pass

def UnicodeDictReader(file_or_str, encoding='utf8', **kwargs):
    import csv

    def decode(s, encoding):
        if s is None:
            return None
        return s.decode(encoding)

    csv_reader = csv.DictReader(file_or_str, **kwargs)

    if not csv_reader.fieldnames:
        raise EmptyCSVError("No fieldnames in CSV reader: empty file?")

    keymap = dict((k, k.decode(encoding)) for k in csv_reader.fieldnames)
    for row in csv_reader:
        yield dict((keymap[k], decode(v, encoding)) for k, v in row.iteritems())

# work around python2's csv.py's difficulty with utf8
# partly cribbed from http://stackoverflow.com/questions/5478659/python-module-like-csv-dictreader-with-full-utf8-support

import csv

class EmptyCSVError(Exception):
    pass


class UnicodeDictReader(object):
    def __init__(self, file_or_str, encoding='utf8', **kwargs):
        self.encoding = encoding
        self.reader = csv.DictReader(file_or_str, **kwargs)

        if not self.reader.fieldnames:
            raise EmptyCSVError("No fieldnames in CSV reader: empty file?")

        self.keymap = dict((k, k.decode(encoding)) for k in self.reader.fieldnames)

    def __iter__(self):
        return (self._decode_row(row) for row in self.reader)

    def _decode_row(self, row):
        return dict(
            (self.keymap[k], self._decode_str(v)) for k, v in row.iteritems()
        )

    def _decode_str(self, s):
        if s is None:
            return None
        return s.decode(self.encoding)

Convert UnicodeDictReader to an iterator class, so that EmptyCSVError will get thrown on instantiation, rather than on iteration.
Convert UnicodeDictReader to an iterator class, so that EmptyCSVError will get thrown on instantiation, rather than on iteration.
