Note that there are some explanatory texts on larger screens.

plurals
  1. POHow to integrate SQLAlchemy and a subclassed Numpy.ndarray smoothly and in a pythonic way?
    primarykey
    data
    text
    <p>I would like to store numpy-arrays with annotations (like <code>name</code>) via SQLAlchemy within a relational database. To do so, </p> <ul> <li>I seperate the numpy array from its data via an data transfere object (<code>DTONumpy</code> as part of <code>MyNumpy</code>).</li> <li>numpy-objects are collected with <code>Container</code>.</li> </ul> <p>What would be a nice and pythonic way to modify <code>Container</code> (from the example below) in a way that it provides as a list directly <code>MyNumpy</code>-objects instead of <code>DTONumpy</code> which is provided by SQLAlchemy?</p> <p>Here is an illustration of the problem:</p> <pre><code>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 </code></pre> <p><code>Container</code> should now provide a list of <code>MyNumpy</code>-objects and <code>MyNumpy</code>-object a reference to the according <code>Container</code>-object (the list and the reference would have to take the SQLAlchemy-mapping into account):</p> <pre><code>type (c2.my_numpy_objects[0]) == MyNumpy &gt;&gt;&gt; True c2.my_numpy_objects.append(MyNumpy ([7,2,5,6], "new data") print c2.dto_numpy_objects[-1].name &gt;&gt;&gt; "new data" </code></pre>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload