用Python在SQLite数据库中插入二进制文件

2024-05-17 10:56:42 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图编写一个简单的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()

我没有收到任何错误消息,但据我所见,记录没有插入。我做错什么了?另外,如何提取存储的文档?谢谢!


Tags: 文档脚本数据库closereadexecutesqliteodt
3条回答

问题:

  1. 你没有显示你运行的完整代码。你不应该让回答者猜测像sqlite.Binary(k)这样的事情。

  2. 基本问题:您没有提交事务。conn.close()之前使用conn.commit()

这个例子有很多问题。我会的 一个接一个地说。

  • 没有错误检查。我们要么使用try/except/finally 构造或使用带关键字的
  • Python方法不像C#属性。您没有运行execute()方法,而是将一些字符串赋给一个对象。(在Python中,方法也是对象。)
  • 非常重要的是,您的代码会受到SQL注入攻击。我们不应该使用Python字符串操作构建SQL语句。我们应该始终使用占位符。
  • 这个例子是不完整的。这就引出了一个棘手的问题。假设存在一个CREATE TABLE语句,那么将创建一个新的隐式事务。必须发出commit()语句才能将数据保存到数据库文件中。在SQLite中,除了SELECT之外的任何语句都会启动隐式事务。(某些数据库,如MySQL,默认情况下处于自动提交模式。这对于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()方法,因为这是由with关键字在幕后处理的。

不确定您正在使用的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]))

使用Python2.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插入blob,并使用str将其作为字符串读回(因为它也使用buffer类型)——如果您只是将其写入磁盘,则不需要后一段(因为文件的write方法接受缓冲区对象和接受字符串一样)。

相关问题 更多 >