2010-07-22 15 views
10

Próbuję napisać prosty skrypt w języku Python, który wstawia dokumenty .odt do bazy danych SQLite. Oto co zrobiłem do tej pory, ale nie wydaje się do pracy:Wstaw plik binarny w bazie danych SQLite za pomocą Pythona

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

ja nie otrzymuję żadnych komunikatów o błędach, ale o ile widzę płyta nie jest włożona. Co ja robię źle? Jak również odzyskać przechowywany dokument? Dzięki!

Odpowiedz

28

Nie wiesz, co to jest sqlite.Binary używasz, ale w każdym razie, oto przykład praca:

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

Uruchomiony z Python 2.6, kod ten pokazuje, jak oczekiwano i życzenia: „\ x00 \ x01 \ x02 \ x07 \ x04 \ x05 \ x0b \ x0c \ r \ x0e \ x0f \ x10 \ x11 \ x12 \ x13 \ x14 \ x15 \ x16 \ x17 \ x18 \ x19 \ X1A \ X1B \ X1C \ X1D \ x1e \ x1f "# $% & \ '() * +, -./'!

Note konieczność stosowania buffer wstawić blob i str aby ją przeczytać z powrotem jako ciąg (ponieważ używa on buffer także jako wynik) - jeśli zamierzasz zapisać go na dysku, ten ostatni fragment nie będzie potrzebny (ponieważ metoda plików write przyjmuje obiekty buforowe równie dobrze, jak przyjmuje ciągi).

+0

Idealnie! Dziękuję bardzo za Twoją pomoc! – dmpop

+0

@dmpop, nie ma za co! –

+0

Dobry przykład, mam podobne pytanie (http://stackoverflow.com/questions/3915888/how-do-i-properly-format-a-stringio-objectpython-and-django-to-be-inted-into) Byłbym bardzo wdzięczny, gdybyś mógł rzucić na to okiem. –

6

Problemy:

  1. Nie przedstawiają pełny kod, który prowadził. Nie należy pozostawiać respondentów zgadujących, co takie rzeczy jak sqlite.Binary(k).

  2. Podstawowy problem: nie dokonałeś transakcji. Użyj conn.commit() przed .

6

Istnieje wiele problemów z podanym przykładem. Będę adres jeden po drugim.

  • Nie ma sprawdzania błędów. Musimy albo użyć konstrukcji try/except/finally , albo użyć słowa kluczowego z.
  • Metody w języku Python nie przypominają właściwości języka C#. Nie używasz metody execute(), przypisujesz jakiś ciąg do obiektu. (W języku Python metodami są też obiekty.)
  • Bardzo ważne jest, że twój kod podlega Injection SQL Injection. Nigdy nie powinniśmy budować instrukcji SQL za pomocą operacji na łańcuchach Pythona. Zawsze powinniśmy używać symboli zastępczych.
  • Przykład jest niekompletny. Co prowadzi do trudnego problemu. Przypuśćmy, że istnieje instrukcja CREATE TABLE, a następnie zostanie utworzona niejawna transakcja . I musi zostać wydana instrukcja commit(), aby zapisać dane w pliku bazy danych. W SQLite każda instrukcja inna niż SELECT rozpoczyna niejawną transakcję. (Niektóre bazy danych, takie jak MySQL, są domyślnie w trybie autocommit. Nie dotyczy to SQLite.)

Oto właściwa przykład roboczych, które będą pisać dokument LibreOffice do Dokumentów tabeli bazy danych 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),)) 

Plik book.odt znajduje się w bieżącym katalogu roboczym. Nie wywoływaliśmy ręcznie metody commit(), ponieważ jest ona obsługiwana za pomocą słowa kluczowego with behind the scene.

+1

Dlaczego dostęp 'sqlite3' jako' lite'? – Tshepang

+0

To tylko mój styl. To trochę skraca kod. –

+0

Ale używasz go tylko raz. To zbyt dziwne ... Nie widzę wygranej. Jeśli wykonujemy liczbę znaków, nie skraca ona kodu. – Tshepang

Powiązane problemy