python + sqlite3 - 无法使 blob 数据正常工作

python + sqlite3 - Can't get blob data to work

我知道这已被多次提及,但我似乎无法让它发挥作用。我正在编写一个 python 程序,它将接收一个 sqlite3 数据库转储文件,分析它并使用数据库迁移工具(称为 yoyo-migrations)重新创建它

我运行正在解决 sqlite3 中的 blob 数据问题以及如何正确格式化它。

这是我的程序执行的基本解释 - 读入转储文件,分成 CREATE 语句、INSERT 语句和其他语句 - 为 CREATEs 生成迁移文件 - 为每个 tables 插入生成一个迁移文件 - 运行 重建数据库的迁移(除了现在它是由迁移构建的)

基本上我得到了一个数据库,需要使用迁移来控制它。这只是第一步(使用迁移工具重建东西)

这里是 table blob table 的创建:

CREATE TABLE blob_table(
    blockid INTEGER PRIMARY KEY,
    block blob
)

然后我创建迁移文件:

#
# file: migrations/0001.create_table.py
# Migration to build tables (autogenerated by parse_dump.py)
#

from yoyo import step
step('CREATE TABLE blob_table( blockid INTEGER PRIMARY KEY, block blob);')

请注意,我只是将其写入文件,然后在最后 运行 迁移。接下来我需要正确的 "seed" 迁移来插入数据。这就是我 运行 遇到麻烦的地方!

# here is an example insert line from the dump
INSERT INTO blob_table VALUES(765,X'00063030F180800FE1C');

所以 X'' 的内容是 blob 数据,我需要编写一个 python 文件,将此数据插入回 table。我有大量数据,所以我使用了 execute many 语法。这是种子迁移文件的样子(示例):

#
# file: migrations/0011.seed_blob_table.py
# Insert seed data for blob table
#

from yoyo import step
import sqlite3

def do_step(conn):
    rows = [
        (765,sqlite3.Binary('00063030303031340494100')),
        (766,sqlite3.Binary('00063030303331341FC5150')),
        (767,sqlite3.Binary('00063030303838381FC0210'))
    ]
    cursor = conn.cursor()
    cursor.executemany('INSERT INTO blob_table VALUES (?,?)', rows)

# run the insert
step(do_step)

我试过使用 sqlite3.Binary()、python 内置 buffer()、两者的组合以及 int('string', base=16)hex() 和很多其他的。无论我做什么,它都不会与转储中的数据库匹配。我的意思是:

如果我并排打开新旧数据库并执行此查询:

# in the new database, it comes out as a string
SELECT * FROM blob_table WHERE blockid=765;
> 765|00063030303031340494100

# in the old database, it displays nothing
SELECT * FROM blob_table WHERE blockid=765;
> 765|

# if I do this in the old one, I get the x'' from the dump
SELECT blockid, quote(block) FROM blob_table WHERE blockid=765;
765|X'00063030303031340494100'

# if I use the quote() in the new database i get something different
SELECT blockid, quote(block) FROM blob_table WHERE blockid=765;
765|X'303030363330333033303330... (truncated, this is longer than the original and only has digits 0-9

我的最终目标是重建数据库并使其与起始数据库(从中创建转储)相同。非常感谢任何有关让 blob 东西起作用的提示!

buffer class 能够处理二进制数据。但是,它会小心保存您提供给它的数据,并且 '00063030303031340494100' 不是二进制数据;它是一个包含数字零、零、零、六等的字符串。

要构建包含二进制数据的字符串,请使用 decode:

import codecs
blob = buffer(codecs.decode(b'00063030303031340494100', 'hex_codec'))