4

Using python, I am trying to import a csv into an sqlite table and use the headers in the csv file to become the headers in the sqlite table. The code runs but the table "MyTable" does not appear to be created. Here is the code:

with open ('dict_output.csv', 'r') as f:
    reader = csv.reader(f)
    columns = next(reader)

#Strips white space in header
    columns = [h.strip() for h in columns]


#reader = csv.DictReader(f, fieldnames=columns)
    for row in reader:
        print(row)

    con = sqlite3.connect("city_spec.db")
    cursor = con.cursor()

#Inserts data from csv into table in sql database.
    query = 'insert into MyTable({0}) values ({1})'
    query = query.format(','.join(columns), ','.join('?' * len(columns)))
    print(query)
    cursor = con.cursor()
    for row in reader:
        cursor.execute(query, row)
#cursor.commit()

    con.commit()

    con.close()

Thanks in advance for any help.

1
  • 1
    where's your "create table" statement? Commented Jan 27, 2017 at 18:25

3 Answers 3

10

You can use Pandas to make this easy (you may need to pip install pandas first):

import sqlite3
import pandas as pd

# load data
df = pd.read_csv('dict_output.csv')

# strip whitespace from headers
df.columns = df.columns.str.strip()

con = sqlite3.connect("city_spec.db")

# drop data into database
df.to_sql("MyTable", con)

con.close()

Pandas will do all of the hard work for you, including create the actual table!

Sign up to request clarification or add additional context in comments.

4 Comments

Script will (might) croak with the 'name=' in the penultimate line. Just remove it since name is a positional parameter anyway.
Are you confident of the need for the strip? I tried omitting it and the sql variable names seem ok. But I'm no pandas expert.
No, but it was in the original code posted and I wanted to match the functionality as closely as possible.
It can't hurt. :)
1

You haven't marked your answer solved yet so here goes.

Connect to the database just once, and create a cursor just once. You can read the csv records only once. I've added code that creates a crude form of the database table based on the column names alone. Again, this is done just once in the loop. Your insertion code works fine.

import sqlite3
import csv

con = sqlite3.connect("city_spec.sqlite") ## these statements belong outside the loop
cursor = con.cursor()  ## execute them just once

first = True
with open ('dict_output.csv', 'r') as f:
    reader = csv.reader(f)
    columns = next(reader)
    columns = [h.strip() for h in columns]
    if first:
        sql = 'CREATE TABLE IF NOT EXISTS MyTable (%s)' % ', '.join(['%s text'%column for column in columns])
        print (sql)
        cursor.execute(sql)
        first = False
    #~ for row in reader:    ## we will read the rows later in the loop
        #~ print(row)

    query = 'insert into MyTable({0}) values ({1})'
    query = query.format(','.join(columns), ','.join('?' * len(columns)))
    print(query)
    cursor = con.cursor()
    for row in reader:
        cursor.execute(query, row)
    con.commit()
    con.close()

Comments

1

You can also do it easy with peewee orm. For this you only use an extension from peewee, the playhouse.csv_loader:

from playhouse.csv_loader import *

db = SqliteDatabase('city_spec.db')

Test = load_csv(db, 'dict_output.csv')

You created the database city_spec.db with the headers as fields and the data from the dict_output.csv

If you don't have peewee you can install it with

pip install peewee

1 Comment

csv_utils extension is no longer included in the playhouse since peewee version 3.0

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.