2

How do you detect the last row in a csv file? It is an iterator but I cannot find a way to detect the last row:

csvfile = open('file.csv', 'r')

reader = csv.DictReader(csvfile, fieldnames)

for idx, row in enumerate(reader, start=1):
    # How to detect last row?
Ethan Furman
  • 63,992
  • 20
  • 159
  • 237
bman
  • 5,016
  • 4
  • 36
  • 69

3 Answers3

2

You can always just convert to a list and take the last element of the list

csvfile = open('file.csv', 'r')

reader = csv.DictReader(csvfile, fieldnames)

all_lines = list(reader)
last_line = all_lines[-1]
Greg
  • 5,422
  • 1
  • 27
  • 32
  • This may cause problems if the file is very large as it will require reading the entire file into memory. –  Jan 30 '15 at 02:59
  • I'm not disagreeing, its up to the user to define which solution best fits the needs of the situation – Greg Jan 30 '15 at 19:29
2

As stated, using next() is probably the best bet

csvfile     = open('file.csv', 'r')

reader = csv.DictReader(csvfile, fieldnames)

mycsv = enumerate(reader, start=1)
idx, row = mycsv.next()
while row:
    try:
       next_set = mycsv.next()
       pass # process set of (idx, row) here
       idx, row = next_set
    except StopIteration:
       pass # process last row here
       idx, row = None # make sure to unset to kill the loop
1

When you want custom behavior, write a custom iterater. Adapting the second example from this answer:

Empty = object()

class BooleanIterator(object):
    """
    True/False tests:  True means there are items still remaining to be used
    """
    def __init__(self, iterator):
        self._iter = iter(iterator)
        self._get_next_value()
    def __next__(self):
        value = self._next_value
        self._get_next_value()
        if value is not Empty:
            return value
        raise StopIteration
    next = __next__                     # python 2.x
    def __bool__(self):
        return self._next_value is not Empty
    __nonzero__ = __bool__              # python 2.x
    def _get_next_value(self):
        self._next_value = next(self._iter, Empty)

In your code:

csvfile = open('file.csv', 'r')

reader = BooleanIterator(csv.DictReader(csvfile, fieldnames))

for idx, row in enumerate(reader, start=1):
    if reader:
        # not the last row
        # process normally
    else:
        # this is the last row!

For more examples of iterators see this answer.

Community
  • 1
  • 1
Ethan Furman
  • 63,992
  • 20
  • 159
  • 237