docs: 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