2010-04-05 11 views
22

Ho un set di file .csv che desidero elaborare. Sarebbe molto più semplice elaborarlo con query SQL. Mi chiedo se c'è un modo per caricare un file .csv e utilizzare il linguaggio SQL per esaminarlo con un linguaggio di scripting come python o ruby. Caricarlo con qualcosa di simile ad ActiveRecord sarebbe fantastico.Database al volo con linguaggi di scripting

Il problema è che non voglio dover eseguire un database da qualche parte prima di eseguire il mio script. Non avrei bisogno di installazioni aggiuntive al di fuori del linguaggio di scripting e di alcuni moduli.

La mia domanda è quale lingua e quali moduli dovrei usare per questa attività. Mi sono guardato intorno e non riesco a trovare nulla che si adatti alle mie esigenze. È possibile?

+0

Per contrassegnare una risposta come preferita (in realtà: come * la * risposta :) è possibile fare clic sul segno di spunta (✓) proprio sotto il conteggio dei voti della risposta scelta. Ad esempio, al momento, la risposta di nosklo ha 13 voti; proprio sotto il triangolo "voto basso" c'è un debole segno di spunta. Clicca qui – tzot

risposta

61

C'è sqlite3, incluso in python. Con esso è possibile creare un database (in memoria) e aggiungere righe ad esso ed eseguire query SQL.

Se si desidera pulito funzionalità di ActiveRecord-come si dovrebbe aggiungere un ORM esterno, come sqlalchemy. Questo è un download separato se

esempio rapida utilizzando sqlalchemy:

from sqlalchemy import create_engine, Column, String, Integer, MetaData, Table 
from sqlalchemy.orm import mapper, create_session 
import csv 
CSV_FILE = 'foo.csv' 
engine = create_engine('sqlite://') # memory-only database 

table = None 
metadata = MetaData(bind=engine) 
with open(CSV_FILE) as f: 
    # assume first line is header 
    cf = csv.DictReader(f, delimiter=',') 
    for row in cf: 
     if table is None: 
      # create the table 
      table = Table('foo', metadata, 
       Column('id', Integer, primary_key=True), 
       *(Column(rowname, String()) for rowname in row.keys())) 
      table.create() 
     # insert data into the table 
     table.insert().values(**row).execute() 

class CsvTable(object): pass 
mapper(CsvTable, table) 
session = create_session(bind=engine, autocommit=False, autoflush=True) 

ora è possibile interrogare il database, filtrando da tutto il campo, ecc

Supponiamo si esegue il codice di cui sopra su questo csv:

name,age,nickname 
nosklo,32,nosklo 
Afila Tun,32,afilatun 
Foo Bar,33,baz 

che creeranno e popolare una tabella in memoria con campi name, age, nickname. È quindi possibile interrogare la tabella:

for r in session.query(CsvTable).filter(CsvTable.age == '32'): 
    print r.name, r.age, r.nickname 

che creeranno automaticamente ed eseguire una query SELECT e restituire le righe corrette.

Un altro vantaggio di usare SQLAlchemy è che, se si decide di utilizzare un altro, più potente banca dati, in futuro, è possibile farlo praticamente senza modificare il codice.

+3

Come segnare questa risposta come preferita? –

+1

Wow grazie, è esattamente quello che volevo. – tmoisan

4

Utilizzare un DB in una libreria come SQLite. Ci sono le versioni Python e Ruby.

Carica il tuo CSV nella tabella, potrebbero esserci moduli/librerie per aiutarti anche qui. Quindi via SQL.

3

file CSV non sono basi di dati - non hanno indici - e qualsiasi simulazione SQL si loro imposta ammonterebbero a poco più di ricerca attraverso l'intera cosa più e più volte.

4

Guardato Perl e Testo: CSV e DBI? Ci sono molti moduli su CPAN per fare esattamente questo. Ecco un esempio (da HERE):

#!/usr/bin/perl 
use strict; 
use warnings; 
use DBI; 

# Connect to the database, (the directory containing our csv file(s)) 

my $dbh = DBI->connect("DBI:CSV:f_dir=.;csv_eol=\n;"); 

# Associate our csv file with the table name 'prospects' 

$dbh->{'csv_tables'}->{'prospects'} = { 'file' => 'prospects.csv'}; 

# Output the name and contact field from each row 

my $sth = $dbh->prepare("SELECT * FROM prospects WHERE name LIKE 'G%'"); 
$sth->execute(); 
while (my $row = $sth->fetchrow_hashref) { 
    print("name = ", $row->{'Name'}, " contact = ", $row->{'Contact'}. "\n"); 
} 
$sth->finish(); 

name = Glenhuntly Pharmacy contact = Paul 
name = Gilmour's Shoes contact = Ringo 

tipo Basta perldoc DBI e perldoc Text :: CSV al prompt dei comandi di più.

3

È possibile utilizzare il linguaggio di scripting per analizzare il file CSV e archiviare i dati in SQLite, che utilizza solo un singolo file per l'archiviazione. Da lì lo hai in un database e puoi eseguire query su di esso.

In alternativa, su Windows è possibile impostare un'origine dati ODBC come file CSV. Ma potrebbe essere difficile automatizzarlo.

1

PHP FlatfileDB disponibili here è una buona opzione se si sta costruendo una web app

2

ho usato la soluzione di nosklo (grazie!), Ma avevo già una chiave primaria (passato come pk_col) all'interno della linea di colonna (prima riga di CSV). Quindi ho pensato di condividere la mia modifica. Ho usato un ternario.

table = Table(tablename, metadata, 
    *((Column(pk_col, Integer, primary_key=True)) if rowname == pk_col else (Column(rowname, String())) for rowname in row.keys())) 
table.create() 
Problemi correlati