可以在SQLite中存储Python类对象吗?

可以在SQLite中存储Python类对象吗?,python,sqlite,serialization,Python,Sqlite,Serialization,我想将Python对象存储到数据库中。可能吗 如果是这样的话,它的一些链接/示例是什么?您可以用来序列化对象。序列化对象可以作为bytearray字段插入sqlite DB f=open('object.dump', 'rw') pickle.dump(obj, f) 现在从文件中读取object.dump,并将其写入sqlite数据库。您可能希望将其编写为二进制数据类型;阅读有关在SQLite中存储二进制数据和blob的内容。请注意,根据,SQLite将此类数据字段的大小限制为1Mb 我认为

我想将Python对象存储到数据库中。可能吗

如果是这样的话,它的一些链接/示例是什么?

您可以用来序列化对象。序列化对象可以作为bytearray字段插入sqlite DB

f=open('object.dump', 'rw')
pickle.dump(obj, f)
现在从文件中读取
object.dump
,并将其写入sqlite数据库。您可能希望将其编写为二进制数据类型;阅读有关在SQLite中存储二进制数据和blob的内容。请注意,根据,SQLite将此类数据字段的大小限制为1Mb


我认为更好的选择是将对象序列化为一个文件,并在数据库中保留文件名,而不是内容。

一个选择是使用O/R映射器,就像它将完成大多数管道一样,将Python对象持久化到数据库中,并且它支持SQLite。如其他地方所述,您还可以使用pickle之类的方法序列化对象,该方法转储对象的表示,该对象可以通过读回和解析来重建。

您不能将对象本身存储在数据库中。您要做的是存储来自对象的数据,然后重新构建它

# When you query the data back it returns instances of your class:

for user in s.query(User):
    print type(user), user.name, user.password
一个好方法是使用优秀的库。它允许您将定义的类映射到数据库中的表。将存储每个映射属性,并可用于重建对象。查询数据库将返回类的实例

有了它,您不仅可以使用sqlite,还可以使用大多数数据库—它目前还支持Postgres、MySQL、Oracle、MS-SQL、Firebird、MaxDB、MS Access、Sybase、Informix和IBM DB2。您可以让用户选择要使用的数据库,因为您基本上可以在这些数据库之间切换,而无需更改代码

还有很多很酷的功能,比如自动
JOIN
s、多态

您可以运行一个快速、简单的示例:

from sqlalchemy import Column, Integer, Unicode, UnicodeText, String
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from sqlalchemy.ext.declarative import declarative_base

from random import choice
from string import letters

engine = create_engine('sqlite:////tmp/teste.db', echo=True)
Base = declarative_base(bind=engine)

class User(Base):
    __tablename__ = 'users'
    id = Column(Integer, primary_key=True)
    name = Column(Unicode(40))
    address = Column(UnicodeText, nullable=True)
    password = Column(String(20))

    def __init__(self, name, address=None, password=None):
        self.name = name
        self.address = address
        if password is None:
            password = ''.join(choice(letters) for n in xrange(10))
        self.password = password

Base.metadata.create_all()

Session = sessionmaker(bind=engine)
s = Session()
然后我可以这样使用它:

# create instances of my user object
u = User('nosklo')
u.address = '66 Some Street #500'

u2 = User('lakshmipathi')
u2.password = 'ihtapimhskal'

# testing
s.add_all([u, u2])
s.commit()
>>> from klepto.archives import sqltable_archive as sql_archive
>>> d = sql_archive(cached=False)
>>> d['a'] = 1  
>>> d['b'] = '1'
>>> d['c'] = min
>>> squared = lambda x:x*x
>>> d['d'] = squared
>>> class Foo(object):
...   def __init__(self, x):
...     self.x = x
...   def __call__(self):
...     return squared(self.x)
... 
>>> f = Foo(2)
>>> d['e'] = Foo
>>> d['f'] = f
>>> 
>>> d
sqltable_archive('sqlite:///:memory:?table=memo' {'a': 1, 'b': '1', 'c': <built-in function min>, 'd': <function <lambda> at 0x10f631268>, 'e': <class '__main__.Foo'>, 'f': <__main__.Foo object at 0x10f63d908>}, cached=False)
>>> 
>>> # min(squared(2), 1)
>>> d['c'](d['f'](), d['a'])
1
>>> 
这将对数据库运行
INSERT
语句

# When you query the data back it returns instances of your class:

for user in s.query(User):
    print type(user), user.name, user.password
该查询将运行
选择users.id作为users\u id,users.name作为users\u name,users.address作为users\u address,users.password作为users\u password

打印结果将是:

<class '__main__.User'> nosklo aBPDXlTPJs
<class '__main__.User'> lakshmipathi ihtapimhskal
nosklo aBPDXlTPJs 拉克什米帕蒂·伊赫塔皮姆斯卡尔
因此,您可以有效地将对象存储到数据库中,这是最好的方法。

您可以选择使用ORM来代替酸洗。这使您可以将数据库中的行映射到对象。请参阅以获取起点。我推荐或。

是的,这是可能的,但有不同的方法,哪种方法合适取决于您的要求

  • 酸洗

    您可以使用该模块序列化对象,然后将这些对象存储在sqlite3中的blob中(或者存储在文本字段中,如果转储是base64编码的)。注意一些可能的问题:

  • 对象关系映射

    您可以使用对象关系映射。这实际上创建了一个“虚拟对象数据库”,可以在编程语言()中使用。对于python,有一个很好的工具包:

您可以使用它将可拾取的对象作为字符串返回,而无需将其写入临时文件

返回的pickle表示形式 将对象设置为字符串,而不是 将其写入文件


有一种相对简单的方法来存储和比较对象,eaven以正确的方式索引这些对象,并限制(使用ubique)包含对象的列。所有这些都不需要使用ORM引擎。可以使用pickle dump存储对象(因此性能可能是一个问题),这里是存储python元组、索引、限制和比较的示例。此方法可以轻松地应用于任何其他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)")


######################### Test ########################

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()

根据您的具体需要,对于这项任务,您可能需要查看Django(www.djangoproject.com)。Django实际上是一个web框架,但它处理的任务之一是允许您将模型定义为python对象(从框架提供的基类继承)。然后,它将自动创建存储这些对象所需的数据库表,sqlite是受支持的后端之一。它还提供了方便的函数来查询数据库并返回一个或多个匹配对象。例如,请参阅关于django中模型的文档:


缺点当然是您必须安装一个完整的web框架,而且(据我所知)您只能存储django支持其属性的对象。此外,它用于存储预定义对象的多个实例,而不是存储多个不同对象的一个实例。根据您的需要,这可能是不切实际的,也可能不是不切实际的。

正如其他人所提到的,答案是肯定的。。。但是首先需要序列化对象。我是一个名为
klepot
的包的作者,该包用于在SQL数据库、HDF归档和其他类型的键值存储中无缝存储python对象

它提供了一个简单的字典界面,如下所示:

# create instances of my user object
u = User('nosklo')
u.address = '66 Some Street #500'

u2 = User('lakshmipathi')
u2.password = 'ihtapimhskal'

# testing
s.add_all([u, u2])
s.commit()
>>> from klepto.archives import sqltable_archive as sql_archive
>>> d = sql_archive(cached=False)
>>> d['a'] = 1  
>>> d['b'] = '1'
>>> d['c'] = min
>>> squared = lambda x:x*x
>>> d['d'] = squared
>>> class Foo(object):
...   def __init__(self, x):
...     self.x = x
...   def __call__(self):
...     return squared(self.x)
... 
>>> f = Foo(2)
>>> d['e'] = Foo
>>> d['f'] = f
>>> 
>>> d
sqltable_archive('sqlite:///:memory:?table=memo' {'a': 1, 'b': '1', 'c': <built-in function min>, 'd': <function <lambda> at 0x10f631268>, 'e': <class '__main__.Foo'>, 'f': <__main__.Foo object at 0x10f63d908>}, cached=False)
>>> 
>>> # min(squared(2), 1)
>>> d['c'](d['f'](), d['a'])
1
>>> 
SQLite 3的适配器和转换器 我很惊讶没有人读过SQLite 3库的文档,因为它说可以通过创建适配器和转换器来实现这一点。例如,假设我们有一个名为“
Point
”的类,我们希望存储它,并在选择它并使用数据库游标的
fetchone
方法返回它时将其返回。让我们让模块知道您从数据库中选择的是一个点

from sqlite3 import connect, register_adaptor, register_converter

class Point:
def __init__(self, x, y):
    self.x, self.y = x, y
def __repr__(self):
    return "(%f;%f)" % (self.x, self.y)

def adapt_point(point):
    return ("%f;%f" % (point.x, point.y)).encode('ascii')

def convert_point(s):
    x, y = list(map(float, s.split(b";")))
    return Point(x, y)

# Register the adapter
register_adapter(Point, adapt_point)

# Register the converter
register_converter("point", convert_point)

p = Point(4.0, -3.2)

# 1) Using declared types
con = connect(":memory:", detect_types=sqlite3.PARSE_DECLTYPES)
con.execute("create table test(p point)")
con.execute("insert into test(p) values (?)", (p,))
cur = con.execute("select p from test")
print("with declared types:", cur.fetchone()[0])
con.close()

# 1) Using column names
con = connect(":memory:", detect_types=sqlite3.PARSE_COLNAMES)
con.execute("create table test(p)")
con.execute("insert into test(p) values (?)", (p,))
cur = con.execute('select p as "p [point]" from test')
print("with column names:", cur.fetchone()[0])
con.close()

首先,感谢大家的回答/指导/提示!!!还有@nosklo,谢谢你的示例代码工作得很有魅力:)非常感谢。我将用你的例子来探索更多关于sqlalchemy的知识-似乎这将符合我的要求..th