Вставить двоичный файл в базу данных SQLite с помощью Python

Я пытаюсь написать простой Python script, который вставляет .odt документы в базу данных SQLite. Вот что я сделал до сих пор, но, похоже, это не работает:

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

Я не получаю никаких сообщений об ошибках, но насколько я вижу, запись не вставлена. Что я делаю не так? Кроме того, как я могу извлечь сохраненный документ? Спасибо!

Ответ 1

Не уверен, что это такое sqlite.Binary, которое вы используете, но, во всяком случае, здесь рабочий пример:

import sqlite3

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

При запуске с Python 2.6 этот код показывает, как ожидалось и желательно:    "\ X00\x01\x02\x03\x04\x05\x06\X07\x08\т\п\x0b\x0c\г\x0e\X0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f!" # $% &\'() * +, -./0123456'

Обратите внимание на необходимость использования buffer, чтобы вставить blob, и str, чтобы прочитать его как строку (поскольку в качестве результата он также использует тип buffer) - если вы просто собираетесь чтобы записать его на диск, последний проход не понадобился (так как метод write файлов принимает объекты буфера так же хорошо, как принимает строки).

Ответ 2

Проблемы:

  • Вы не указали полный код, который вы использовали. Вы не должны оставлять ответчиков, угадывая, что такое sqlite.Binary(k).

  • Основная проблема: вы не совершали транзакции. Используйте conn.commit() до conn.close().

Ответ 3

В данном примере существует несколько проблем. я буду обращайтесь к ним один за другим.

  • Проверка ошибок отсутствует. Нам либо нужно использовать try/except/finally построить или использовать ключевое слово с.
  • Методы Python не похожи на свойства С#. Вы не используете метод execute(), вы назначаете некоторую строку объекту. (В Python методы тоже являются объектами.)
  • Очень важно, чтобы ваш код подвергался атакам SQL Injection. Мы никогда не должны создавать инструкции SQL, используя строковые операции Python. Мы всегда должны использовать заполнители.
  • Пример неполный. Это приводит к сложной проблеме. Предположим, что существует инструкция CREATE TABLE, тогда будет создана новая неявная транзакция. А для вывода данных в файл базы данных должен быть выдан оператор commit(). В SQLite любой оператор, отличный от SELECT, запускает неявную транзакцию. (Некоторые базы данных, такие как MySQL, по умолчанию работают в режиме autocommit. Это не относится к SQLite.)

Вот правильный рабочий пример, который будет записывать документ LibreOffice в Документы таблица базы данных 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), ))

Файл book.odt находится в текущем рабочем каталоге. Мы не вызывали метод commit() вручную, так как это обрабатывается ключевым словом "за кулисами".