2010-01-12 20 views

Respuesta

44

No puede almacenar el objeto en el DB. Lo que debes hacer es almacenar los datos del objeto y reconstruirlos más tarde.

Una buena forma es utilizar la excelente biblioteca SQLAlchemy. Te permite asignar tu clase definida a una tabla en la base de datos. Todos los atributos mapeados se almacenarán y se pueden usar para reconstruir el objeto. Consultar la base de datos devuelve instancias de su clase.

Con él puede utilizar no solo sqlite, sino la mayoría de las bases de datos. Actualmente también es compatible con Postgres, MySQL, Oracle, MS-SQL, Firebird, MaxDB, MS Access, Sybase, Informix e IBM DB2. Y puede hacer que su usuario elija cuál quiere usar, porque básicamente puede cambiar entre esas bases de datos sin cambiar el código en absoluto.

También hay una gran cantidad de características interesantes - como automáticas JOIN s, polimorfar ...

A, rápido ejemplo simple que puede funcionar:

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

Entonces puede utilizar de esta manera:

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

que funcionaría INSERT declaraciones en contra de la base de datos.

# 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 

Esa consulta correría SELECT users.id AS users_id, users.name AS users_name, users.address AS users_address, users.password AS users_password.

El resultado impreso sería:

<class '__main__.User'> nosklo aBPDXlTPJs 
<class '__main__.User'> lakshmipathi ihtapimhskal 

Así que estás almacenar eficazmente su objeto en la base de datos, la mejor manera.

+0

En primer lugar, gracias a todos por sus respuestas/guía/consejos! y @ nosklo, gracias código de ejemplo funcionó como un encanto :) Muchas gracias. Voy a explorar más acerca de sqlalchemy con su ejemplo, parece que se adaptará a mis requisitos ... gracias a todos de nuevo. –

+0

Primero, gracias a todos por sus respuestas/guía/consejos! y @ nosklo, gracias código de ejemplo funcionó como un encanto :) Muchas gracias. Exploraré más acerca de sqlalchemy con su ejemplo. Parece que se adaptará más a mis requisitos que a la salmuera. Gracias a todos nuevamente. –

+1

Sí, la 'salmuera' en mi humilde opinión ** no ** vale la pena. Parece genial y todo, pero usted ** no puede ** filtrar/unir/agregar datos ya que el objeto se almacena como * blob *, lo que le hace perder el objetivo de usar una base de datos en primer lugar. – nosklo

1

Puede usar pickle para serializar el objeto. El objeto serializado se puede insertar en la base de datos sqlite como un campo bytearray.

f=open('object.dump', 'rw') 
pickle.dump(obj, f) 

Ahora lea object.dump del archivo, y escribirla en el SQLite DB. Es posible que desee escribirlo como un tipo de datos binarios; lea sobre el almacenamiento de datos binarios y blob en SQLite here. Tenga en cuenta que según this source, SQLite limita el tamaño de dicho campo de datos a 1Mb.

Creo que una mejor opción sería serializar su objeto en un archivo, y mantener el archivo nombre, no contenido, en la base de datos.

+0

Esto está lejos de ser una buena práctica. Almacenar objetos en escabeche como blobs en una base de datos subvierte el razonamiento para usar una base de datos, buscabilidad. almacenar los nombres de archivo en la base de datos debido a las restricciones de tamaño de archivo no mejora esta opción. – devsnd

0

Una opción es utilizar un correlacionador O/R como SQLObject. Hará la mayor parte de la plomería para mantener el objeto Python en una base de datos y es compatible con SQLite. Como se mencionó en otra parte, también puede serializar el objeto usando un método como pickle, que vacía una representación del objeto que puede reconstruir volviendo a leer y analizar.

10

Sí, es posible, pero hay diferentes enfoques y cuál es el adecuado, dependerá de sus requisitos.

  • Decapado

    Se puede utilizar el módulo de pickle para serializar objetos, entonces almacenar estos objetos en un blob en sqlite3 (o un campo de texto, si el volcado es, por ejemplo base64 codificado). Ser consciente de algunos problemas posibles: questions/198692/can-i-pickle-a-python-dictionary-into-a-sqlite3-text-field

  • Object-Relational Mapping

    Puede utilizar el objeto de mapeo relacional. Esto crea, en efecto, una "base de datos de objetos virtuales" que se puede usar desde el lenguaje de programación (Wikipedia). Para Python, hay un buen conjunto de herramientas para eso: sqlalchemy.

5

Puede utilizar pickle.dumps, sus objetos de retorno pickable como cadenas, que no necesitarían para escribirlo en los archivos temporales.

devolver la representación en escabeche de el objeto como una cadena, en lugar de escribirlo en un archivo.

import pickle 

class Foo: 
    attr = 'a class attr' 

picklestring = pickle.dumps(Foo) 
0

hay forma relativamente sencilla de almacenar y comparar objetos, eaven para indexar esos objetos manera correcta y para restringir (con ubique) columnas que contienen objetos. Y todo eso sin usar motores ORM. El mástil de objetos se almacenará utilizando el volcado de pickle (por lo que el rendimiento puede ser un problema) Aquí hay un ejemplo para almacenar tuplas de Python, restringir la indexación y comparar. Este método se puede aplicar fácilmente a cualquier otra clase de python. Todo lo que se necesita se explica en la documentación de python sqlite3 (alguien ya publicó el enlace). De todos modos aquí todo se armó en el siguiente ejemplo:

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

En función de sus necesidades específicas, podría ser vale la pena analizar Django (www.djangoproject.com) para esta tarea. Django es en realidad un marco web, pero una de las tareas que maneja es permitirle definir Modelos como objetos Python (heredando de una clase base proporcionada por el marco). A continuación, creará automáticamente las tablas de la base de datos necesarias para almacenar esos objetos, y sqlite se encuentra entre los servidores compatibles. También proporciona funciones útiles para consultar la base de datos y devolver uno o más objetos coincidentes. Véase, por ejemplo, la documentación acerca de los modelos de Django:

http://docs.djangoproject.com/en/1.9/topics/db/models/

El inconveniente es, por supuesto que tiene que instalar un marco web completa, y (por lo que yo recuerdo) sólo se puede almacenar objetos cuyos atributos son apoyado por django. Además, está hecho para almacenar muchas instancias de objetos predefinidos, no para almacenar una instancia de cada uno de muchos objetos diferentes. Dependiendo de sus necesidades, esto puede o no ser poco práctico.

Cuestiones relacionadas