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

web*_*org 34 python sqlite serialization

我想将Python对象存储到SQLite数据库中.那可能吗?

如果是这样的话会有什么链接/例子呢?

nos*_*klo 59

您无法将对象本身存储在数据库中.您所做的是存储来自对象的数据并在以后重建它.

一个好方法是使用优秀的SQLAlchemy库.它允许您将定义的类映射到数据库中的表.每个映射的属性都将被存储,并可用于重建对象.查询数据库会返回类的实例.

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

还有很多很酷的功能 - 比如自动JOINs,多态...

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

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()
Run Code Online (Sandbox Code Playgroud)

然后我可以像这样使用它:

# 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()
Run Code Online (Sandbox Code Playgroud)

这会对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
Run Code Online (Sandbox Code Playgroud)

该查询将运行SELECT users.id AS users_id, users.name AS users_name, users.address AS users_address, users.password AS users_password.

打印结果如下:

<class '__main__.User'> nosklo aBPDXlTPJs
<class '__main__.User'> lakshmipathi ihtapimhskal
Run Code Online (Sandbox Code Playgroud)

所以你有效地将对象存储到数据库中,这是最好的方法.

  • 是的,恕我直言'泡菜'不值得.它似乎很酷,但是你不能**过滤/加入/ agreggate数据,因为对象存储为*blob*,从而首先破坏了使用数据库的目的. (3认同)
  • 首先,感谢大家的回答/指导/提示!!!和@ nosklo,谢谢你的示例代码工作得很好:) 非常感谢。我将通过您的示例探索更多有关 sqlalchemy 的信息-似乎这将满足我的要求..再次感谢大家。 (2认同)

mik*_*iku 15

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


小智 12

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()
Run Code Online (Sandbox Code Playgroud)


YOU*_*YOU 8

你可以使用pickle.dumps,它的返回可选对象作为字符串,你不需要将它写入临时文件.

将对象的pickled表示作为字符串返回,而不是将其写入文件.

import pickle

class Foo:
    attr = 'a class attr'

picklestring = pickle.dumps(Foo)
Run Code Online (Sandbox Code Playgroud)

  • 应该是公认的答案,说实话。非常感谢! (2认同)