用于CSV导入的SQLite事务

时间:2013-08-05 16:06:19

标签: python csv sqlite raspberry-pi

我是python的新手,并且一直在使用我的raspberry pi来启动并运行脚本以将数百万个传感器数据记录导入sqlite。我想在事务中执行此操作以提高流程效率。我试图将事务分解为10k块,如下所示:Python CSV to SQLite

到目前为止我已经

import csv, sqlite3, time

def chunks(data, rows=10000):
    for i in range (0, len(data), rows):
            yield data[i:i+rows]

if __name__ == "__main__":

    t = time.time()

con = sqlite3.connect('test.db')
cur = con.cursor()
cur.execute("DROP TABLE IF EXISTS sensor;")
cur.execute("CREATE TABLE sensor(key INT, reading REAL);")

filename = 'dummy.csv'
reader = csv.reader(open(filename,"r"))
divdata = chunks(reader)

for chunk in divdata:
    cur.execute('BEGIN TRANSACTION')

    for col1, col2 in chunk:
            cur.execute('INSERT INTO sensor (key, reading) VALUES (?, ?)', (col1, col2))

    con.execute('COMMIT')

我在python 3.2.3中遇到以下错误:

Traceback (most recent call last):
File "/home/pi/test1.py", line 20, in <module>
for chunk in divdata:
File "/home/pi/test1.py", line 4, in chunks
for i in range (0, len(data), rows):
TypeError: object of type '_csv.reader' has no len()

我显然在某个部分搞乱了部分,因为一切(基本插入)在没有块和事务的情况下工作正常。任何帮助表示赞赏。

3 个答案:

答案 0 :(得分:2)

你的SQL看起来没问题。我确实发现您的CSV阅读器存在问题:它不支持len() chunks()中使用它的方式。

您可以使用更典型的for row in data循环,也可以使用one of the techniques described in this thread,如果您需要将文件分成多个块。

答案 1 :(得分:0)

任务中的代码段有两个问题:

  1. chunks来电中的读者应该包含在list()
  2. &#39; commit&#39;应该使用连接的commit()方法
  3. 参见固定代码:

    import csv, sqlite3, time
    
    def chunks(data, rows=10000):
        for i in range (0, len(data), rows):
                yield data[i:i+rows]
    
    if __name__ == "__main__":
    
        t = time.time()
    
    con = sqlite3.connect('test.db')
    cur = con.cursor()
    cur.execute("DROP TABLE IF EXISTS sensor;")
    cur.execute("CREATE TABLE sensor(key INT, reading REAL);")
    
    filename = 'dummy.csv'
    reader = csv.reader(open(filename,"r"))
    divdata = chunks(list(reader))
    
    for chunk in divdata:
        cur.execute('BEGIN TRANSACTION')
    
        for col1, col2 in chunk:
                cur.execute('INSERT INTO sensor (key, reading) VALUES (?, ?)', (col1, col2))
    
        con.commit()
    

答案 2 :(得分:0)

问题是您从csv.reader方法获得的对象不支持len()函数。事实上,这个CSV阅读器只在被指示时才会读取,因此,它不知道文件中有多少条记录。

因此,您需要更新chunks方法来处理不知道要分块的事物的数量。用这个替换该功能:

def chunks(data, n=10000):
    buffer = [None] * n
    idx = 0
    for record in data:
        buffer[idx] = record
        idx += 1
        if idx == n:
            yield buffer
            buffer = [None] * n
            idx = 0
    if idx > 0:
        yield buffer[:idx]

它的作用是:只要有要检索的记录,它就会一直从文件中检索记录,并且每个n行都会发出n条记录列表。例如:

>>> for c in chunks(range(10), 3):
...     print(c)
...
[0, 1, 2]
[3, 4, 5]
[6, 7, 8]
[9]