web-dev-qa-db-ja.com

Python)を使用してSQLiteデータベースにバイナリファイルを挿入します

.odtドキュメントをSQLiteデータベースに挿入する単純な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()

エラーメッセージは表示されませんが、レコードが挿入されていないことがわかります。私は何が間違っているのですか?また、保存されているドキュメントを抽出して戻すにはどうすればよいですか?ありがとう!

15
dmpop

それが何であるかわからない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\t\n\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f! "#$%&\ '()* +、-。/ 0123456 '

ブロブを挿入するにはbufferを使用し、文字列として読み戻すにはstrを使用する必要があることに注意してください(結果としてbufferタイプも使用するため)-ディスクに書き込むだけの場合は、後者のパッセージは必要ありません(ファイルのwriteメソッドは文字列を受け入れるのと同じようにバッファオブジェクトを受け入れるため)。

33
Alex Martelli

与えられた例には複数の問題があります。それらを一つずつ取り上げていきます。

  • エラーチェックはありません。 try/exception/finally構文を使用するか、withキーワードを使用する必要があります。
  • PythonメソッドはC#プロパティとは異なります。 execute()メソッドを実行しておらず、オブジェクトに文字列を割り当てています。 (Pythonでは、メソッドもオブジェクトです。)
  • 非常に重要なのは、コードがSQLインジェクション攻撃の影響を受けることです。 Python文字列操作を使用してSQLステートメントを作成することは絶対にしないでください。常にplaceholdersを使用する必要があります。
  • 例は不完全です。これはトリッキーな問題につながります。 _CREATE TABLE_ステートメントがあったとすると、新しい暗黙のトランザクションが作成されます。また、データをデータベースファイルに保存するには、commit()ステートメントを発行する必要があります。 SQLiteでは、SELECT以外のステートメントは暗黙的なトランザクションを開始します。 (MySQLなどの一部のデータベースは、デフォルトで自動コミットモードになっています。これはSQLiteには当てはまりません。)

これは、SQLiteデータベースのDocsテーブルにLibreOfficeドキュメントを書き込む適切な作業例です。

_#!/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キーワードによって処理されるためです。

9
Jan Bodnar

問題:

  1. 実行した完全なコードを表示しませんでした。回答者にsqlite.Binary(k)のようなものを推測させてはいけません。

  2. 基本的な問題:トランザクションをコミットしませんでした。conn.commit()の前にconn.close()を使用してください。

7
John Machin