Импорт файла CSV в sqllite3 с использованием функционального программирования на Python - PullRequest
0 голосов
/ 07 марта 2019

Я знаю, что есть другие посты, но я не смог найти конкретный вопрос, который имел в виду. Я использую CSV-файл US_baby_names. и хотите импортировать этот CSV-файл построчно в sqlite3 в виде таблицы.

Я могу создать таблицу под названием хранилище. Затем я пытаюсь прочитать строки в файле CSV и положить его в эту таблицу, но я, должно быть, делаю что-то не так.

import sqlite3 as sql
from sqlite3 import Error
import csv

def CreateConnection ( dbFileName ):
   try:
      conn = sql.connect(dbFileName)
      return conn
   except Error as e:
      print(e)

   return None

def CreateNew( dbConnection, new):
     sql =  """INSERT INTO storage (dat, Id, Name, Year, group, subgroup, Count)
        VALUES (?,?,?,?,?,?,?)"""

     try:
       cursor = dbConnection.cursor()
       cursor.execute(sql, new)
       return cursor.lastrowid
     except Error as e:
       print(e)

def Main():
  database = "storage.db"
  dbConnection = CreateConnection(database)

  with open('storage.csv', 'rb') as fin:
     dr = csv.DictReader(fin)
     to_db = [(i['dat'], i['Id'], i['Name'], i['Year'], i['group'], i['subgroup'], i['Count']) \
        for i in dr]

    cursor.executemany(CreateNew(sql, to_db))

    dbConnection.close()

if __name__ == "__main__":
  Main()

Я считаю, что мой курсор неверен, но я не могу понять, что еще делать ..

Спасибо

1 Ответ

2 голосов
/ 07 марта 2019

Вы почти правы с большей частью своего кода, но:

  • в cursor.execute(sql, new) вы передаете итеративный new в sqlite3.execute() (для этого требуется простой оператор SQL) вместо sqlite3.executemany().
  • Более того, результатом CreateNew() является целое число lastrowid, и вы передаете этот результат в executemany().
  • Вы должны использовать Connection.commit(), чтобы сохранить изменения в базе данных, и Connection.rollback(), чтобы отменить их.
  • Вы должны открыть файл для класса csv.DictReader как текстовый файл , в режиме r или rt.
  • Наконец, помните, что sqlite3.Connection - это менеджер контекста, поэтому вы можете использовать его в операторе with.

Это должен быть желаемый результат:

import sqlite3 as sql
from sqlite3 import Error
import csv


def create_table(conn):
    sql = "CREATE TABLE IF NOT EXISTS baby_names("\
        "dat TEXT,"\
        "Id INTEGER PRIMARY KEY,"\
        "Name TEXT NOT NULL,"\
        "Year INTEGER NOT NULL,"\
        "Gender TEXT NOT NULL,"\
        "State TEXT NOT NULL,"\
        "Count INTEGER)"

    conn.execute(sql)
    conn.execute("DELETE FROM baby_names")

def select_all(conn):
    for r in conn.execute("SELECT * FROM baby_names").fetchall():
        print(r)


def execute_sql_statement(conn, data):
    sql = "INSERT INTO baby_names "\
        "(dat, Id, Name, Year, Gender, State, Count) "\
        "VALUES (?,?,?,?,?,?,?)"

    try:
        cursor = conn.executemany(sql, data)
    except Error as e:
        print(e)
        conn.rollback()
        return None
    else:
        conn.commit()
        return cursor.lastrowid

def main():        
    with sql.connect('baby_names.db') as conn, open('US_Baby_Names_right.csv', 'r') as fin:
        create_table(conn)

        dr = csv.DictReader(fin)
        data = [(i['dat'], i['Id'], i['Name'], i['Year'], i['Gender'], i['State'], i['Count']) for i in dr ]

        lastrowid = execute_sql_statement(conn, data)

        select_all(conn)


main()

Я добавил create_table() функцию только для проверки моего кода. Я также составил пример файла теста следующим образом:

dat,Id,Name,Year,Gender,State,Count
1,1,John,1998,M,Washington,2
2,2,Luke,2000,M,Arkansas,10
3,3,Carrie,1999,F,Texas,3

Выход функции select_all():

('1',1,'John',1998,'M','Washington',2)
('2',2,'Luke',2000,'M','Arkansas',10)
('3',3,'Carrie',1999,'F','Texas',3)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...