0

我正在使用 sqlite3 表来存储 python dicts(utf8 内容),并且序列化是使用 JSON 完成的。它在 python2.7 中运行良好,但在 3.3 中失败。

架构:

CREATE TABLE mytable
  (id INTEGER, book TEXT NOT NULL, d JSON NOT NULL, priority INTEGER NOT NULL DEFAULT(3), 
   PRIMARY KEY (id, book))

插入值时,dict 被序列化为json.dumps(d). 故障部分正在检索以前保存的值。

import sys
import sqlite3
import json

filename = 'mydb.db'
sqlite3.register_converter('JSON', json.loads)
conn = sqlite3.connect(filename, detect_types=sqlite3.PARSE_DECLTYPES|sqlite3.PARSE_COLNAMES)
c = conn.cursor()
c.execute('''SELECT book, id, d, priority FROM mytable''')
print(c.fetchall())

上面的脚本在使用 python2.7 执行时可以正常工作。但是,使用 3.3 会发生 TypeError:

Traceback (most recent call last):
  File "tests/py3error_debug.py", line 15, in <module>
    c.execute('''SELECT book, id, d, priority FROM mytable''')
  File "/usr/local/Cellar/python3/3.3.2/Frameworks/Python.framework/Versions/3.3/lib/python3.3/json/__init__.py", line 319, in loads
    return _default_decoder.decode(s)
  File "/usr/local/Cellar/python3/3.3.2/Frameworks/Python.framework/Versions/3.3/lib/python3.3/json/decoder.py", line 352, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
TypeError: can't use a string pattern on a bytes-like object

我无法发现 2.7 和 3.3 JSON 模块(尤其是关于json.loads)之间的本质区别,而且我已经没有想法了。

4

1 回答 1

1

根据Python 3 json 模块文档

json 模块总是产生str对象,而不是 bytes 对象。...

根据Python 3 sqlite3.register_converter 文档

注册一个可调用函数以将数据库中的字节串转换为自定义 Python 类型。...

如果你尝试加载 bytesstring json,你会得到 TypeError:

>>> json.loads('"0"')
'0'
>>> json.loads(b'"0"')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python3.3/json/__init__.py", line 319, in loads
    return _default_decoder.decode(s)
  File "/usr/lib/python3.3/json/decoder.py", line 352, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
TypeError: can't use a string pattern on a bytes-like object

json.loads您应该在使用bytes.decode调用之前将字节转换为 str 。

sqlite3.register_converter('JSON', lambda x: json.loads(x.decode('utf-8')))
于 2013-08-24T02:26:07.343 回答