Python:迭代通过空白csv

时间:2016-09-06 16:41:48

标签: python csv error-handling sqlite

我是一个新的python用户并且遇到了问题。如果解决方案很明显,我会提前道歉。

我打算能够获取潜在的大量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()将csv文件.reader对象,sqlite3数据库连接和游标对象以及要创建和插入的输出表作为输入。

直到最近,当我尝试输入一个仅包含标题的csv文件时,它一直工作正常。调用.next()方法后出现StopIteration错误。如何避免/我误解/忽视什么?

我感谢所有的帮助,欢迎任何批评!

1 个答案:

答案 0 :(得分:1)

您之前已经耗尽了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来说无关紧要;如果只存在标题而不存在,那么就不会执行实际的"..."语句。

请注意,我使用li { font-size: 100%; } li:nth-child(1) { font-size: 90%; } li:nth-child(2) { font-size: 80%; } li:nth-child(3) { font-size: 70%; } li:nth-child(4) { font-size: 60%; } 双引号来正确引用表名,请参阅SQLite keywords;单引号用于字符串文字值,而不是表名。