2010-05-22 7 views
69

Ho un file CSV e voglio importare in blocco questo file nel mio database sqlite3 usando Python. il comando è ".import .....". ma sembra che non possa funzionare in questo modo. Qualcuno può darmi un esempio di come farlo in sqlite3? Sto usando Windows per ogni evenienza. GrazieImportazione di un file CSV in una tabella di database sqlite3 utilizzando Python

+3

Fornire il comando ** actual ** che non ha funzionato e il messaggio di errore ** actual **. "import ...." potrebbe essere qualsiasi cosa. "non può funzionare" è troppo vago per noi da indovinare. Senza dettagli, non possiamo aiutare. –

+1

il comando effettivo come ho detto è ".import" e dice l'errore di sintassi nuovo ".import" – Hossein

+8

In realtà postare il comando effettivo nella domanda. Si prega di pubblicare effettivamente il messaggio di errore effettivo nella domanda. Per favore non aggiungere commenti che semplicemente ripetono le cose. Si prega di aggiornare la domanda con copia e incolla effettive di ciò che si sta effettivamente facendo. –

risposta

95
import csv, sqlite3 

con = sqlite3.connect(":memory:") 
cur = con.cursor() 
cur.execute("CREATE TABLE t (col1, col2);") # use your column names here 

with open('data.csv','rb') as fin: # `with` statement available in 2.5+ 
    # csv.DictReader uses first line in file for column headings by default 
    dr = csv.DictReader(fin) # comma is default delimiter 
    to_db = [(i['col1'], i['col2']) for i in dr] 

cur.executemany("INSERT INTO t (col1, col2) VALUES (?, ?);", to_db) 
con.commit() 
con.close() 
+2

Nel caso avessi avuto gli stessi problemi che ho fatto: Assicurati di cambiare col1 e col2 nelle intestazioni delle colonne nel file csv. E chiudi la connessione al database chiamando con.close() alla fine. – Jonas

+0

Grazie, @ Jonas. Post aggiornato – bernie

+0

Continuo a ricevere 'non tutti gli argomenti convertiti durante la formattazione della stringa 'quando provo questo metodo. – Whitecat

10

Il comando .import è una funzionalità dello strumento da riga di comando sqlite3. Per farlo in Python, dovresti semplicemente caricare i dati usando le varie funzioni di Python, come lo csv module, e inserendo i dati come al solito.

In questo modo, hai anche il controllo su quali tipi sono inseriti, piuttosto che fare affidamento sul comportamento apparentemente non documentato di sqlite3.

+0

Non è necessario preparare l'inserto. L'origine delle istruzioni SQL e i risultati compilati sono conservati in una cache. –

+0

@John Machin: C'è un collegamento a come SQLite fa questo? –

+0

@Marcelo: Se sei interessato a COME è fatto (perché?), Guarda nella sorgente sqlite o chiedi sulla mailing list sqlite. –

8

Molte grazie per Bernie answer! Dovuto modificare un po '- ecco cosa ha funzionato per me:

import csv, sqlite3 
conn = sqlite3.connect("pcfc.sl3") 
curs = conn.cursor() 
curs.execute("CREATE TABLE PCFC (id INTEGER PRIMARY KEY, type INTEGER, term TEXT, definition TEXT);") 
reader = csv.reader(open('PC.txt', 'r'), delimiter='|') 
for row in reader: 
    to_db = [unicode(row[0], "utf8"), unicode(row[1], "utf8"), unicode(row[2], "utf8")] 
    curs.execute("INSERT INTO PCFC (type, term, definition) VALUES (?, ?, ?);", to_db) 
conn.commit() 

mio file di testo (PC.txt) si presenta così:

1 | Term 1 | Definition 1 
2 | Term 2 | Definition 2 
3 | Term 3 | Definition 3 
6
#!/usr/bin/python 
# -*- coding: utf-8 -*- 

import sys, csv, sqlite3 

def main(): 
    con = sqlite3.connect(sys.argv[1]) # database file input 
    cur = con.cursor() 
    cur.executescript(""" 
     DROP TABLE IF EXISTS t; 
     CREATE TABLE t (COL1 TEXT, COL2 TEXT); 
     """) # checks to see if table exists and makes a fresh table. 

    with open(sys.argv[2], "rb") as f: # CSV file input 
     reader = csv.reader(f, delimiter=',') # no header information with delimiter 
     for row in reader: 
      to_db = [unicode(row[0], "utf8"), unicode(row[1], "utf8")] # Appends data from CSV file representing and handling of text 
      cur.execute("INSERT INTO neto (COL1, COL2) VALUES(?, ?);", to_db) 
      con.commit() 
    con.close() # closes connection to database 

if __name__=='__main__': 
    main() 
+0

Dov'è la funzione unicode()? –

49

Creazione di una connessione SQLite in un file su disco viene lasciato come esercizio per il lettore ... ma ora c'è un due-liner resa possibile dalla libreria panda

df = pandas.read_csv(csvfile) 
df.to_sql(table_name, conn, if_exists='append', index=False) 
+0

grazie. Ho avuto un problema con il panda. il mio CSV è delimitato da ';' e avere ',' nelle voci. panda dà errore su read_csv. qualsiasi impostazione per leggere le voci con virgole w/out temporaneamente sostituite? –

+3

usa sep = ';'. La documentazione di panda illustra chiaramente come affrontarlo. –

+2

c'è un modo per usare i panda ma senza usare la RAM ?, ho un enorme .csv (7gb) che non posso importare come un dataframe e quindi aggiunto al DB. –

9

I miei 2 centesimi (più ge Neric):

import csv, sqlite3 
import logging 

def _get_col_datatypes(fin): 
    dr = csv.DictReader(fin) # comma is default delimiter 
    fieldTypes = {} 
    for entry in dr: 
     feildslLeft = [f for f in dr.fieldnames if f not in fieldTypes.keys()] 
     if not feildslLeft: break # We're done 
     for field in feildslLeft: 
      data = entry[field] 

      # Need data to decide 
      if len(data) == 0: 
       continue 

      if data.isdigit(): 
       fieldTypes[field] = "INTEGER" 
      else: 
       fieldTypes[field] = "TEXT" 
     # TODO: Currently there's no support for DATE in sqllite 

    if len(feildslLeft) > 0: 
     raise Exception("Failed to find all the columns data types - Maybe some are empty?") 

    return fieldTypes 


def escapingGenerator(f): 
    for line in f: 
     yield line.encode("ascii", "xmlcharrefreplace").decode("ascii") 


def csvToDb(csvFile, outputToFile = False): 
    # TODO: implement output to file 

    with open(csvFile,mode='r', encoding="ISO-8859-1") as fin: 
     dt = _get_col_datatypes(fin) 

     fin.seek(0) 

     reader = csv.DictReader(fin) 

     # Keep the order of the columns name just as in the CSV 
     fields = reader.fieldnames 
     cols = [] 

     # Set field and type 
     for f in fields: 
      cols.append("%s %s" % (f, dt[f])) 

     # Generate create table statement: 
     stmt = "CREATE TABLE ads (%s)" % ",".join(cols) 

     con = sqlite3.connect(":memory:") 
     cur = con.cursor() 
     cur.execute(stmt) 

     fin.seek(0) 


     reader = csv.reader(escapingGenerator(fin)) 

     # Generate insert statement: 
     stmt = "INSERT INTO ads VALUES(%s);" % ','.join('?' * len(cols)) 

     cur.executemany(stmt, reader) 
     con.commit() 

    return con 
+0

se len (feildslLeft)> 0: sempre vero, quindi sollevando un'eccezione. Si prega di rivedere e correggere questo. – shubham

+0

Un modo per farlo senza dover usare fseek(), in modo che possa essere utilizzato sui flussi? – mwag

4

È possibile farlo usando blaze & odo efficiente

import blaze 
csv_path = 'data.csv' 
bz.odo(csv_path, 'sqlite:///data.db::data') 

Odo memorizzerà il file CSV per data.db (database SQLite) nello schema data

o se si utilizza odo direttamente, senza blaze. In entrambi i casi va bene. Leggi questo documentation

Problemi correlati