How can I prevent or trap StopIteration exception in the yield-calling function?

You can trap the StopIteration exception in the lexical scope of the buggy function this way:

import csv  # essential!

def buggy(csvfile):
    with open(csvfile) as stream:

        reader = csv.reader(stream)

        try:
            yield next(reader)
        except StopIteration:
            yield 'dummy value'

        for row in reader:
            yield row

You basically manually request the first value from the reader iterator and

  • if this succeeds, the first line is read from the csv file and is yielded to the caller of buggy function
  • if this fails, as is the case for empty csv files, some string e.g. dummy value is yielded to prevent the caller of the buggy function from crashing

Afterwards, if the csv file was not empty, the remaining rows will be read (and yielded) in the for cycle.


EDIT: to illustrate why the other variation of mymod.py mentioned in the question does not work, I've added some print statements to it:

import csv  # essential!

def buggy(csvfile):
    with open(csvfile) as stream:

        reader = csv.reader(stream)

        try:
            print('reading first row')
            firstrow = next(reader)
        except StopIteration:
            print('no first row exists')
            firstrow = None

        if firstrow != None:
            print('yielding first row: ' + firstrow)
            yield firstrow

        for row in reader:
            print('yielding next row: ' + row)
            yield row

        print('exiting function open')

Running it gives the following output:

% ./myscript.py empty_input.csv first
reading first row
no first row exists
exiting function open
Traceback (most recent call last):
  File "myscript.py", line 15, in <module>
    main(*sys.argv[1:])
  File "myscript.py", line 9, in main
    print_row(next(mymod.buggy(csvfile)))

That shows, that in case that the input file is empty, the first try..except block correctly handles the StopIteration exception and that the buggy function continues on normally.
The exception that the caller of the buggy gets in this case is due to the fact that the buggy function does not yield any value before completing.