Вставьте двоичный файл в базу данных SQLite с помощью Python - PullRequest
13 голосов
/ 22 июля 2010

Я пытаюсь написать простой скрипт на Python, который вставляет документы .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()

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

Ответы [ 3 ]

32 голосов
/ 22 июля 2010

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

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

При запуске с 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 для вставки большого двоичного объекта и str для чтения его обратно в виде строки (поскольку в результате он также использует тип buffer) - если вы просто собираетесь для записи его на диск последний отрывок не понадобится (поскольку метод файлов write принимает объекты буфера так же, как он принимает строки).

9 голосов
/ 03 марта 2013

Есть несколько проблем с данным примером.Я буду обращаться к ним один за другим.

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

Вот правильный рабочий пример, который записывает документ LibreOffice в таблицу Docs:база данных 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 () вручную, поскольку он обрабатывается ключевым словом with «за кулисами».

7 голосов
/ 22 июля 2010

Проблемы:

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

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

...