2010-05-22 47 views
69

Tengo un archivo CSV y quiero importar en bloque este archivo en mi base de datos sqlite3 usando Python. el comando es ".import .....". pero parece que no puede funcionar así. ¿Alguien puede darme un ejemplo de cómo hacerlo en sqlite3? Estoy usando Windows por las dudas. GraciasImportación de un archivo CSV en una tabla de base de datos sqlite3 usando Python

+3

Proporcione el comando ** actual ** que no funcionó y el mensaje de error ** real **. "importar ..." podría ser cualquier cosa. "no se puede trabajar" es demasiado vago para que podamos adivinar. Sin detalles, no podemos ayudar. –

+1

el comando real como dije es ".import" y dice error de sintaxis nuevo ".import" – Hossein

+8

Por favor, publique realmente el comando real en la pregunta. Por favor, publique el mensaje de error real en la pregunta. Por favor, no agregue comentarios que simplemente repitan cosas. Actualice la pregunta con copiar y pegar realmente lo que está haciendo en realidad. –

Respuesta

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

En caso de que tuvieras los mismos problemas que yo: Asegúrate de cambiar col1 y col2 a los encabezados de las columnas en el archivo csv. Y cierre la conexión a la base de datos llamando a con.close() al final. – Jonas

+0

Gracias, @Jonas. Publicación actualizada. – bernie

+0

Sigo obteniendo 'no todos los argumentos convertidos durante el formateo de cadenas' cuando intento este método. – Whitecat

10

El comando .import es una característica de la herramienta de línea de comandos sqlite3. Para hacerlo en Python, simplemente debes cargar los datos usando las facilidades que tenga Python, como el csv module, e insertar los datos como de costumbre.

De esta manera, también tiene control sobre qué tipos se insertan, en lugar de confiar en el comportamiento aparentemente indocumentado de sqlite3.

+0

No es necesario preparar la inserción. La fuente de las declaraciones SQL y los resultados compilados se guardan en una memoria caché. –

+0

@John Machin: ¿Hay un enlace a cómo SQLite hace esto? –

+0

@Marcelo: si está interesado en CÓMO se hace (¿por qué?), Busque en la fuente de sqlite o pregunte en la lista de correo de sqlite. –

8

Muchas gracias por Bernie answer! Tuvo que ajustar un poco - esto es lo que funcionó para mí:

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() 

Mi archivo de texto (PC.txt) tiene el siguiente aspecto:

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

¿Dónde está la función Unicode()? –

49

Crear una conexión SQLite en un archivo en el disco se deja como ejercicio para el lector ... pero ahora hay dos forro hecho posible gracias a la biblioteca de pandas

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

gracias. Tengo un problema con panda. mi csv está delimitada por ';' y tiene ',' en las entradas. panda da error en read_csv. ¿Alguna configuración para leer entradas con comas sin reemplazar temporalmente? –

+3

use sep = ';'. La documentación de los pandas describe claramente cómo lidiar con esto. –

+2

¿hay alguna forma de usar pandas pero sin usar la RAM ?, tengo un enorme .csv (7gb) que no puedo importar como un marco de datos y luego anexado al DB. –

9

Mis 2 centavos de dólar (más 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

si len (feildslLeft)> 0: siempre es verdadero, por lo que se genera una excepción. Por favor revise y corrija esto. – shubham

+0

¿Alguna manera de hacer esto sin tener que fseek(), para que pueda usarse en las transmisiones? – mwag

4

Usted puede hacer esto utilizando blaze & odo eficiente

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

Odo almacenará el archivo csv a data.db (base de datos SQLite) bajo el esquema data

o bien utilizar odo directamente, sin blaze. De cualquier manera está bien. Lea esto documentation

Cuestiones relacionadas