Python: StopIteration error being raised iterating through blank csv
<p>I'm a new python user and have an issue. I apologize in advance if the solution is obvious.</p>

<p>I intend to be able to take a potentially large amount of csv files and jam them into a database which I can then use sql to query for reporting and other sweet stuff and I have the following code:</p>

<pre><code>import csv

# Establishes a db connection and returns connection and cursor obj
# creates dbName.db file in given location
def openDB (dbName,location):

    import sqlite3,os

    os.chdir(location)

    conn = sqlite3.connect(dbName)
    c = conn.cursor()

    return conn,c

# Uses connection, cursor, csv obj and writes into table
def insertFromCsv (csvObj,connection,cursor,tableName):

    c = cursor

    # Just added this condition to check for blank files
    # but I'm not sure if this is appropriate..
    rowCount = sum(1 for row in csvObj)
    if rowCount &gt; 0:
        csvObj.next()
        i = 0
        for row in csvObj:
            tablerow = ", ".join('"' + value + '"' for value in row)
            insertSQL = "INSERT INTO '%s' VALUES (%s)" %   (tableName,tablerow)
        c.execute(insertSQL)
        i += 1

    connection.commit()
    print '%s rows committed to table %s' % (i, tableName)

# creates the .reader obj
reader = csv.reader(csvFile) 
# extract column names from csv header
tableFields = reader.next()
# formats the column names for the INSERT statement coming up
tableFields = ", ".join('"' + field + '"' for field in tableFields)

DB = openDB('foo.db','../bar')
tableName = myTable
insertFromCsv(reader,DB[0],DB[1],myTable)
</code></pre>

<p>insertFromCsv() takes as input a csv file .reader object, sqlite3 database connection and cursor objects, and an output table to create and insert into.</p>

<p>It has been working alright until recently when I tried to input a csv file which consisted of just a header. I got a StopIteration error after calling the .next() method. How can this be avoided/ what am I misunderstanding/overlooking?</p>

<p>I appreciate all the help and welcome any criticism!</p>

<p>You have exhausted the <code>csvObj</code> iterator on the line before:</p>

<pre><code>rowCount = sum(1 for row in csvObj)
</code></pre>

<p>Once an iterator is exhausted, you can't call <code>next()</code> on it anymore without that raising <code>StopIteration</code>; you have reached the end of the iterator already.</p>

<p>If you want to test for a blank CSV file, read <em>one</em> row with the <a href="https://docs.python.org/2/library/functions.html#next" rel="nofollow"><code>next()</code> function</a>, which can be given a default. <code>next(csvObj, None)</code> would return <code>None</code> rather than propagate the <code>StopIteration</code> exception when the iterator is exhausted for example.</p>

<p>Next, use <em>SQL parameters</em> to create one generic SQL statement, then use <code>cursor.executemany()</code> to have the database pull in all the rows and insert them for you:</p>

<pre><code>header = next(csvObj, None)
if header:
    tablerow = ", ".join(['?'] * len(row))
    insertSQL = 'INSERT INTO "%s" VALUES (%s)' % (tableName, tablerow)
    c.executemany(insertSQL, csvObj)
</code></pre>

<p>The <code>?</code> is a SQL parameter placeholder; <code>executemany()</code> will fill these from each row from <code>csvObj</code>.</p>

<p>It won't matter to the <code>cursor.executemany()</code> call if <code>csvObj</code> actually yieds any rows; if only the header exists and nothing more, then no actual <code>INSERT</code> statements are executed.</p>

<p>Note that I used <code>"..."</code> double quotes to correctly quote the table name, see <a href="https://www.sqlite.org/lang_keywords.html" rel="nofollow"><em>SQLite keywords</em></a>; single quotes are for string literal values, not table names.</p>

python sqlite csv error-handling sqlite3