Me gustaría almacenar numpy-arrays con anotaciones (como name
) a través de SQLAlchemy dentro de una base de datos relacional. Para hacerlo,¿Cómo integrar SQLAlchemy y una Numpy.ndarray subclassed suavemente y de una manera pitthonic?
- I separar la matriz numpy de sus datos a través de un objeto transfere datos (
DTONumpy
como parte deMyNumpy
). - numpy-objects se recogen con
Container
.
¿Cuál sería una manera agradable y Pythonic modificar Container
(en el ejemplo a continuación) de una manera que se proporciona como una lista directamente MyNumpy
-Objetos en lugar de DTONumpy
que es proporcionada por SQLAlchemy?
Aquí es una ilustración del problema:
import numpy as np
import zlib
import sqlalchemy as sa
from sqlalchemy.orm import relationship, scoped_session, sessionmaker
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.types import TypeDecorator, CHAR
DBSession = scoped_session(sessionmaker())
Base = declarative_base()
#### New SQLAlchemy-Type #####################
class NumpyType (sa.types.TypeDecorator):
impl = sa.types.LargeBinary
def process_bind_param(self, value, dialect):
return zlib.compress(value.dumps(), 9)
def process_result_value(self, value, dialect):
return np.loads(zlib.decompress(value))
##############################################
class DTONumpy(Base):
__tablename__ = 'dtos_numpy'
id = sa.Column(sa.Integer, primary_key=True)
amount = sa.Column('amount', NumpyType)
name = sa.Column('name', sa.String, default='')
container_id = sa.Column(sa.ForeignKey('containers.id'))
container_object = relationship(
"Container",
uselist=False,
backref='dto_numpy_objects'
)
def __init__(self, amount, name=None):
self.amount = np.array(amount)
self.name = name
class Container(Base):
__tablename__ = 'containers'
id = sa.Column(sa.Integer, primary_key=True)
name = sa.Column(sa.String, unique=True)
# HERE: how to access DTONumpy BUT as MyNumpy-Objects in a way that MyNumpy
# is smoothly integrated into SQLAlchemy
class MyNumpy(np.ndarray):
_DTO = DTONumpy
def __new__(cls, amount, name=''):
dto = cls._DTO(amount=amount, name=name)
return cls.newByDTO(dto)
@classmethod
def newByDTO(cls, dto):
obj = np.array(dto.amount).view(cls)
obj.setflags(write=False) # Immutable
obj._dto = dto
return obj
@property
def name(self):
return self._dto.name
if __name__ == '__main__':
engine = sa.create_engine('sqlite:///:memory:', echo=True)
DBSession.configure(bind=engine)
Base.metadata.create_all(engine)
session = DBSession()
mn1 = MyNumpy ([1,2,3], "good data")
mn2 = MyNumpy ([2,3,4], "bad data")
# Save MyNumpy-Objects
c1 = Container()
c1.name = "Test-Container"
c1.dto_numpy_objects += [mn1._dto, mn2._dto] # not a good ui
session.add(c1)
session.commit()
# Load MyNumpy-Objects
c2 = session.query(Container).filter_by(name="Test-Container").first()
# Ugly UI:
mn3 = MyNumpy.newByDTO(c2.dto_numpy_objects[0])
mn4 = MyNumpy.newByDTO(c2.dto_numpy_objects[1])
name3 = mn3._dto.name
name4 = mn4._dto.name
Container
ahora debe proporcionar una lista de MyNumpy
-Objetos y MyNumpy
-objeto una referencia a la Container
-objeto de acuerdo (la lista y la referencia tendría que tomar la SQLAlchemy-mapping en cuenta):
type (c2.my_numpy_objects[0]) == MyNumpy
>>> True
c2.my_numpy_objects.append(MyNumpy ([7,2,5,6], "new data")
print c2.dto_numpy_objects[-1].name
>>> "new data"
Ha considerado [PyTables] (http://www.pytables.org/moin)? Descubrí que las bases de datos relacionales pueden ser problemáticas cuando se trabaja con matrices n-dimensionales. –
Con la tabla de cifrado Francesc proporciona un paquete impresionante sobre la biblioteca de hdf5, y estoy totalmente de acuerdo en que, en general, esta es la mejor solución para trabajar con datos numéricos organizados de jerarquía. Pero el problema ilustrado es una estructura de datos ilustrada más completa, que es parte de un proyecto que requiere una base de datos relacional como back-end. –
Una forma de hacerlo sería implementar un ListView que convierta los tipos. Para eso ver [aquí] (http://stackoverflow.com/questions/8984692/how-can-i-change-in-python-the-return-input-type-of-a-list-that-is-implemented -un). –