def reader(fname, header=True, sep="\t", skip_while=None,
        quotechar='"'):
    r"""
    for each row in the file `fname` generate dicts If `header` is True
    or lists if `header` is False. The dict keys are drawn from the first
    line.
    If `header` is a list of names, those will be used as the dict keys.
    If `header` is 'ordered', the function will yield ordered dicts.
    If `header` is a callable, it will be called for each row.
    If `header` is collections.namedtuple, a namedtuple object will be yielded
    for each row using the first row as the names.
    skip_while is a function that returns False when it is ready to start
    consuming. this could be something like:

    skip_while = lambda toks: toks[0].startswith('#')

    >>> import sys
    >>> if sys.version_info[0] < 3:
    ...     from StringIO import StringIO
    ... else:
    ...     from io import StringIO
    >>> get_str = lambda : StringIO("a\tb\tname\n1\t2\tfred\n11\t22\tjane")
    >>> expected = [{'a': '1', 'b': '2', 'name': 'fred'},
    ... {'a': '11', 'b': '22', 'name': 'jane'}]
    >>> list(reader(get_str())) == expected
    True

    >>> expected = [['a', 'b', 'name'],
    ...             ['1', '2', 'fred'], ['11', '22', 'jane']]
    >>> list(reader(get_str(), header=False)) == expected
    True
    """
    if isinstance(fname, int_types):
        fname = sys.argv[fname]
    if not isinstance(fname, basestring) and \
        isinstance(fname, types.GeneratorType):
            line_gen = fname
    elif sep is None:
        def _line_gen(f, sep):
            if sep is None:
                for line in nopen(f):
                    yield line.rstrip("\r\n").split()
        line_gen = _line_gen(fname, sep)
    elif isinstance(fname, basestring) and fname.endswith((".xls")):
        line_gen = xls_reader(fname)
    else:
        # simple separator, e.g. comma or "\t, "\s", etc.
        if len(sep) == 1 or (len(sep) == 2 and sep[0] == '\\'):
            dialect = csv.excel
            dialect.delimiter = sep
            dialect.quotechar = quotechar
            if not quotechar:
                dialect.quoting = csv.QUOTE_NONE
            line_gen = csv.reader(nopen(fname), dialect=dialect)
        else: # sep is a regex.
            import re
            sep = re.compile(sep)
            def _re_line_gen(f, sep):
                for line in nopen(f):
                    yield sep.split(line.rstrip("\r\n"))
            line_gen = _re_line_gen(fname, sep)

    if skip_while:
        from itertools import chain
        l = next(line_gen)
        while skip_while(l):
            l = next(line_gen)
        line_gen = chain.from_iterable(([l], line_gen))

    if header is namedtuple:
        header = next(line_gen)
        header[0] = header[0].lstrip("#")
        nt = namedtuple('namedtuple', header)
        for toks in line_gen:
            yield nt._make(toks)
        raise StopIteration

    # they sent in a class or function that accepts the toks.
    elif callable(header):
        for toks in line_gen:
            yield header(toks)

        raise StopIteration

    a_dict = dict
    # if header is 'ordered', then use an ordered dictionary.
    if header == "ordered":
        try:
            from collections import OrderedDict as a_dict
        except ImportError:
            from ordereddict import OrderedDict as a_dict
        header = True

    if header is True:
        header = next(line_gen)
        header[0] = header[0].lstrip("#")

    if header:
        for toks in line_gen:
            yield a_dict(izip(header, toks))
    else:
        for toks in line_gen:
            yield toks
r"""
    for each row in the file `fname` generate dicts If `header` is True
    or lists if `header` is False. The dict keys are drawn from the first
    line.
    If `header` is a list of names, those will be used as the dict keys.
    If `header` is 'ordered', the function will yield ordered dicts.
    If `header` is a callable, it will be called for each row.
    If `header` is collections.namedtuple, a namedtuple object will be yielded
    for each row using the first row as the names.
    skip_while is a function that returns False when it is ready to start
    consuming. this could be something like:

    skip_while = lambda toks: toks[0].startswith('#')

    >>> import sys
    >>> if sys.version_info[0] < 3:
    ...     from StringIO import StringIO
    ... else:
    ...     from io import StringIO
    >>> get_str = lambda : StringIO("a\tb\tname\n1\t2\tfred\n11\t22\tjane")
    >>> expected = [{'a': '1', 'b': '2', 'name': 'fred'},
    ... {'a': '11', 'b': '22', 'name': 'jane'}]
    >>> list(reader(get_str())) == expected
    True

    >>> expected = [['a', 'b', 'name'],
    ...             ['1', '2', 'fred'], ['11', '22', 'jane']]
    >>> list(reader(get_str(), header=False)) == expected
    True