2010-07-22 22 views
10

Sto provando a scrivere un semplice script Python che inserisce documenti .odt in un database SQLite. Ecco quello che ho fatto finora, ma non sembra funzionare:Inserire il file binario nel database SQLite con Python

f=open('Loremipsum.odt', 'rb') 
k=f.read() 
f.close() 
cursor.execute="INSERT INTO notes (note) VALUES ('%s')" %(sqlite.Binary(k)) 
cursor.close() 
conn.close() 

non ho ricevuto alcun messaggio di errore, ma per quanto posso vedere il record non è inserita. Che cosa sto facendo di sbagliato? Inoltre, come posso estrarre il documento memorizzato? Grazie!

risposta

28

Non so cosa è che sqlite.Binary si sta utilizzando, ma, in ogni caso, ecco un esempio di lavoro:

import sqlite3 

# let's just make an arbitrary binary file... 
with open('/tmp/abin', 'wb') as f: 
    f.write(''.join(chr(i) for i in range(55))) 
# ...and read it back into a blob 
with open('/tmp/abin', 'rb') as f: 
    ablob = f.read() 

# OK, now for the DB part: we make it...: 
db = sqlite3.connect('/tmp/thedb') 
db.execute('CREATE TABLE t (thebin BLOB)') 
db.execute('INSERT INTO t VALUES(?)', [buffer(ablob)]) 
db.commit() 
db.close() 

# ...and read it back: 
db = sqlite3.connect('/tmp/thedb') 
row = db.execute('SELECT * FROM t').fetchone() 
print repr(str(row[0])) 

Quando viene eseguito con Python 2.6, questo codice mostra, come previsto e desiderato: '\ x00 \ x01 \ x02 \ x03 \ x04 \ x05 \ x06 \ x07 \ x08 \ t \ n \ x0b \ x0c \ r \ X0E \ x0f \ x10 \ x11 \ x12 \ x13 \ x14 \ x15 \ x16 \ x17 \ x18 \ x19 \ X1A \ X1B \ X1c \ x1d \ x1e \ x1f "# $% & \ '() * +, -./'!

nota la necessità di utilizzare buffer per inserire il blob, e str di leggerlo indietro come una stringa (poiché utilizza lo buffer tipo come risultato): se lo scriverai su disco, quest'ultimo passaggio non sarebbe necessario (poiché il metodo write di file accetta gli oggetti buffer altrettanto bene quanto accetta le stringhe).

+0

Perfetto! Grazie mille per il vostro aiuto! – dmpop

+0

@ dmpop, prego! –

+0

Bel esempio, ho una domanda simile (http://stackoverflow.com/questions/3915888/how-do-i-properly-format-a-stringio-objectpython-and-django-to-be-inserted-into) , Sarei molto grato se potessi dare un'occhiata a questo. –

6

Problemi:

  1. Non hanno mostrato il codice completo che è stato eseguito. Non dovresti lasciare che i rispondenti indovinino cose come sqlite.Binary(k).

  2. Problema fondamentale: non hai eseguito il commit della transazione. Utilizzare conn.commit() prima del conn.close().

6

Ci sono diversi problemi con l'esempio fornito. Mi occuperò dello ad uno ad uno.

  • Nessun controllo degli errori. O dobbiamo utilizzare il costrutto try/except/finally o utilizzare lo con la parola chiave.
  • I metodi Python non sono come le proprietà C#. Non stai utilizzando il metodo execute(), stai assegnando una stringa ad un oggetto. (In Python anche i metodi sono oggetti.)
  • Molto importante è che il codice sia soggetto agli attacchi SQL Injection. Non dovremmo mai costruire istruzioni SQL usando le operazioni con le stringhe Python. Dovremmo sempre usare segnaposto.
  • L'esempio è incompleto. Il che porta a un problema delicato. Supponendo che ci fosse un'istruzione CREATE TABLE, sarebbe stata creata una nuova transazione implicita . E una dichiarazione commit() deve essere emessa per salvare i dati nel file di database. In SQLite, qualsiasi istruzione diversa da SELECT avvia una transazione implicita. (Alcuni database, come MySQL, sono in modalità di autocommit per impostazione predefinita, non è vero per SQLite.)

Ecco un esempio di lavoro adeguato, che scriverà un documento LibreOffice a una Documenti tabella di un database SQLite:

#!/usr/bin/python 
# -*- coding: utf-8 -*- 

import sqlite3 as lite 

fl = open('book.odt', 'rb') 

with fl: 
    data = fl.read() 

con = lite.connect('test.db') 

with con: 

    cur = con.cursor()  

    cur.execute("CREATE TABLE IF NOT EXISTS Docs(Data BLOB)") 

    sql = "INSERT INTO Docs(Data) VALUES (?)" 
    cur.execute(sql, (lite.Binary(data),)) 

Il file book.odt si trova nella directory di lavoro corrente. Non abbiamo chiamato manualmente il metodo commit(), poiché questo è gestito dalla parola chiave behind the scenes.

+1

Perché accedere a 'sqlite3' come' lite'? – Tshepang

+0

Questo è solo il mio stile. Riduce leggermente il codice. –

+0

Ma lo usi solo una volta. È troppo strano ... Non vedo una vittoria. Se facciamo un conteggio di personaggi, non accorcia il codice. – Tshepang

Problemi correlati