2016-09-06 2 views
1

Я новый пользователь python и имею проблему. Я заранее извиняюсь, если решение очевидно.Ошибка Python: StopIteration, повторяющаяся через пустой csv

я намерен быть в состоянии принять потенциально большое количество файлов CSV и застревание их в базу данных, которую я могу затем использовать SQL для запроса отчетов и других сладостей и у меня есть следующий код:

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 > 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) 

insertFromCsv() принимает в качестве входных данных объект cvv .reader, соединение с базой данных sqlite3 и объекты курсора и таблицу вывода для создания и вставки.

Он работал нормально до недавнего времени, когда я попытался ввести файл csv, состоящий только из заголовка. Я получил ошибку StopIteration после вызова метода .next(). Как этого можно избежать/что я недопонимаю?

Я ценю всю помощь и приветствую любую критику!

+1

Что вы ожидаете 'csvObj.next()' делать? Вы только что исчерпали итератор 'csvObj', используя на нем' sum() ', поэтому вы не можете прочитать больше строк в этой точке. –

ответ

0

Вы исчерпали csvObj итератор на линии перед:

rowCount = sum(1 for row in csvObj) 

После итератор исчерпан, вы не можете назвать next() на него больше без этого повышения StopIteration; вы уже достигли конца итератора.

Если вы хотите протестировать пустой CSV-файл, прочитайте номер с next() function, который может быть задан по умолчанию. next(csvObj, None) вернет None, а не распространяет исключение StopIteration, когда итератор исчерпан, например.

Далее используйте параметры SQL создать один общее заявление SQL, а затем использовать cursor.executemany() иметь базу данных тянуть во всех строках и вставить их для вас:

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

? является параметр SQL заполнителя ; executemany() заполнит их из каждой строки от csvObj.

Не имеет значения для звонка cursor.executemany(), если csvObj фактически просочился в любые строки; если существует только заголовок и ничего больше, то никаких действительных операторов INSERT не выполняется.

Обратите внимание, что я использовал "..." двойные кавычки, чтобы правильно указать имя таблицы, см. SQLite keywords; одинарные кавычки предназначены для строковых литералов, а не для имен таблиц.

+0

Ahaaa Я знал, что это то, что я неправильно понял. Я на самом деле никогда не буду ожидать полностью пустой файл, только один с только заголовком. это влияет на что-либо? – edaniley

+0

@edaniley: тогда 'executemany()' просто не будет выполнять SQL-запросы, так как 'csvObj' будет тогда пустым. –

+0

Хорошо! хорошо выглядит, за исключением того, что для целей контрольной суммы не сохраняется строка. есть ли способ использовать executemany все время подсчета строк? – edaniley

Смежные вопросы