【问题标题】:Python, Sqlite3 - How to convert a list to a BLOB cellPython,Sqlite3 - 如何将列表转换为 BLOB 单元格
【发布时间】:2010-10-06 22:18:21
【问题描述】:

将 python 中的列表作为二进制数据(即 BLOB 单元)转储到 sqlite3 DB 中的最优雅的方法是什么?

data = [ 0, 1, 2, 3, 4, 5 ]
# now write this to db as binary data
# 0000 0000
# 0000 0001
# ...
# 0000 0101

【问题讨论】:

    标签: python sqlite


    【解决方案1】:

    Brian 的解决方案似乎符合您的需求,但请记住,使用该方法您只需将数据存储为字符串。

    如果您想将原始二进制数据存储到数据库中(这样它不会占用太多空间),请将您的数据转换为 Binary sqlite 对象,然后将其添加到您的数据库中.

    query = u'''insert into testtable VALUES(?)'''
    b = sqlite3.Binary(some_binarydata)
    cur.execute(query,(b,))
    con.commit()
    

    (由于某种原因,python 文档中似乎没有记录)

    以下是关于 sqlite BLOB 数据限制的一些说明:

    http://effbot.org/zone/sqlite-blob.htm

    【讨论】:

      【解决方案2】:

      假设您希望将其视为 8 位无符号值序列,请使用 array 模块。

      a = array.array('B', data)
      >>> a.tostring()
      '\x00\x01\x02\x03\x04\x05'
      

      如果您想将数据视为不同的类型,请使用与'B' 不同的类型代码。例如。 'b' 表示有符号字节序列,'i' 表示有符号整数。

      【讨论】:

        【解决方案3】:

        我有同样的问题,我正在考虑用另一种方式解决这个问题。

        我认为pickle 模块正是为这样的事情完成的(python 对象的序列化)

        示例(此示例用于转储到文件...但我认为它很容易用于数据库存储)

        保存:

        # Save a dictionary into a pickle file.
        import pickle
        favorite_color = { "lion": "yellow", "kitty": "red" }
        pickle.dump( favorite_color, open( "save.p", "w" ) )
        

        加载中:

        # Load the dictionary back from the pickle file.
        import pickle
        favorite_color = pickle.load( open( "save.p" ) )
        

        恕我直言,我认为这种方式更优雅、更安全(适用于任何 python 对象)。

        那是我的 2 美分

        更新: After doing a bit of search on my idea,他们在我的解决方案中显示了一些陷阱(我无法在该字段上进行 sql 搜索)。但我仍然认为这是一个不错的解决方案(如果您不需要搜索该字段。

        【讨论】:

        • 请注意,pickle 模块不安全并且可能不正确。通常最好使用 JSON 等更安全、更标准化的序列化协议。
        【解决方案4】:

        在 SourceForge 上查看这个涵盖任意 Python 对象(包括列表、元组、字典等)的通用解决方案:

        y_serial.py 模块 :: 使用 SQLite 存储 Python 对象

        “序列化 + 持久化 :: 在几行代码中,将 Python 对象压缩并注释为 SQLite;然后稍后通过关键字按时间顺序检索它们,无需任何 SQL。数据库存储无模式数据的最有用的“标准”模块。”

        http://yserial.sourceforge.net

        【讨论】:

        • 虽然严格来说不是对 OPs 问题的一个好答案,但我必须说我遵循了您指向 yserial 的链接,并且该模块非常适合任何需要在 sqlite 中存储和检索 Python 对象的项目。谢谢!
        【解决方案5】:

        可以将对象数据存储为 pickle dump、jason 等,但也可以对它们进行索引、限制它们并运行使用这些索引的选择查询。这是元组的示例,可以轻松应用于任何其他 python 类。所有需要的都在 python sqlite3 文档中进行了解释(有人已经发布了链接)。无论如何,所有这些都放在以下示例中:

        import sqlite3
        import pickle
        
        def adapt_tuple(tuple):
            return pickle.dumps(tuple)    
        
        sqlite3.register_adapter(tuple, adapt_tuple)    #cannot use pickle.dumps directly because of inadequate argument signature 
        sqlite3.register_converter("tuple", pickle.loads)
        
        def collate_tuple(string1, string2):
            return cmp(pickle.loads(string1), pickle.loads(string2))
        
        #########################
        # 1) Using declared types
        con = sqlite3.connect(":memory:", detect_types=sqlite3.PARSE_DECLTYPES)
        
        con.create_collation("cmptuple", collate_tuple)
        
        cur = con.cursor()
        cur.execute("create table test(p tuple unique collate cmptuple) ")
        cur.execute("create index tuple_collated_index on test(p collate cmptuple)")
        
        cur.execute("select name, type  from sqlite_master") # where type = 'table'")
        print(cur.fetchall())
        
        p = (1,2,3)
        p1 = (1,2)
        
        cur.execute("insert into test(p) values (?)", (p,))
        cur.execute("insert into test(p) values (?)", (p1,))
        cur.execute("insert into test(p) values (?)", ((10, 1),))
        cur.execute("insert into test(p) values (?)", (tuple((9, 33)) ,))
        cur.execute("insert into test(p) values (?)", (((9, 5), 33) ,))
        
        try:
            cur.execute("insert into test(p) values (?)", (tuple((9, 33)) ,))
        except Exception as e:
            print e
        
        cur.execute("select p from test order by p")
        print "\nwith declared types and default collate on column:"
        for raw in cur:
            print raw
        
        cur.execute("select p from test order by p collate cmptuple")
        print "\nwith declared types collate:"
        for raw in cur:
            print raw
        
        con.create_function('pycmp', 2, cmp)
        
        print "\nselect grater than using cmp function:"
        cur.execute("select p from test where pycmp(p,?) >= 0", ((10, ),) )
        for raw in cur:
            print raw
        
        cur.execute("select p from test where pycmp(p,?) >= 0", ((3,)))
        for raw in cur:
            print raw 
        
        print "\nselect grater than using collate:"
        cur.execute("select p from test where p > ?", ((10,),) )
        for raw in cur:
            print raw  
        
        cur.execute("explain query plan select p from test where p > ?", ((3,)))
        for raw in cur:
            print raw
        
        cur.close()
        con.close()
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-07-04
          • 1970-01-01
          • 2021-12-01
          • 2020-07-11
          • 1970-01-01
          相关资源
          最近更新 更多