2010-07-22 22 views
10

Estoy tratando de escribir un script simple de Python que inserte documentos .odt en una base de datos SQLite. Esto es lo que he hecho hasta ahora, pero no parece funcionar:Insertar archivo binario en la base de datos 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() 

no recibo ningún mensaje de error, pero por lo que puedo ver, no se inserta el disco. ¿Qué estoy haciendo mal? Además, ¿cómo puedo extraer el documento almacenado? ¡Gracias!

Respuesta

28

No estoy seguro que es que sqlite.Binary que está utilizando, pero, de todos modos, esto es un ejemplo de trabajo:

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

Cuando se ejecuta con Python 2.6, este código de muestra, como se espera y se desea: '\ 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 necesidad de utilizar buffer para insertar la burbuja, y str para leerlo volver como una cadena (ya que usa el buffer escriba también como resultado) - si va a escribirlo en el disco, el último pasaje no sería necesario (dado que el método de archivos write acepta los objetos del búfer igual de bien que acepta cadenas).

+0

¡Perfecto! ¡Muchas gracias por tu ayuda! – dmpop

+0

@dmpop, de nada! –

+0

Buen ejemplo, tengo una pregunta similar (http://stackoverflow.com/questions/3915888/how-do-i-properly-format-a-stringio-objectpython-and-django-to-be-inserted-into) , Estaría muy agradecido si pudieras echarle un vistazo. –

6

Problemas:

  1. Usted no mostraron el código completo que se ejecutó. No debe dejar contestar adivinando qué cosas como sqlite.Binary(k).

  2. Problema fundamental: No ha confirmado la transacción. Utilice conn.commit() antes de conn.close().

6

Existen varios problemas con el ejemplo dado. Voy a abordarlos uno por uno.

  • No hay error al verificar. Necesitamos usar la construcción try/except/finally o usar la con la palabra clave.
  • Los métodos de Python no son como las propiedades de C#. No está ejecutando el método execute(), está asignando alguna cadena a un objeto. (En Python, los métodos también son objetos).
  • Muy importante es que su código está sujeto a SQL Injection attacks. Nunca debemos construir sentencias de SQL utilizando operaciones de cadenas de Python. Siempre debemos usar marcadores de posición.
  • El ejemplo está incompleto. Lo que conduce a un problema complicado. Suponiendo que haya una instrucción CREATE TABLE, se creará una nueva transacción implícita . Y se debe emitir una declaración commit() para guardar los datos en el archivo de la base de datos. En SQLite, cualquier instrucción que no sea SELECT inicia una transacción implícita. (Algunas bases de datos, como MySQL, están en modo autocommit por defecto. Esto no es cierto para SQLite.)

Aquí es un ejemplo de trabajo adecuada, lo que va a escribir un documento de LibreOffice a una Docs tabla de una base de datos 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),)) 

El archivo book.odt se encuentra en el directorio de trabajo actual. No llamamos manualmente al método commit(), ya que esto es manejado por la palabra clave behind.

+1

¿Por qué acceder 'sqlite3' como' lite'? – Tshepang

+0

Este es solo mi estilo. Acorta el código un poco. –

+0

Pero solo lo usa una vez. Es muy extraño ... No veo una victoria. Si hacemos un recuento de caracteres, no acorta el código. – Tshepang

Cuestiones relacionadas