Pedro,

I don't really have much of anything special as far as the connection
goes--SQLAlchemy already does a pretty awesome job of handling all
that for you.  I just keep a module-level variable that I can import
as needed, and call a function in that module to set up the connection
with settings from a config file.

As far as the models/mapping goes, I have all of the tables, classes,
and mapping between then defined in one module, and I can just import
from there whenever needed.  Nothing about sessions/connections in
there at all--that way there's no need to worry about them.  It's
really a pretty ordinary set-up.

Unfortunately, all this code is for work, so I can't share it.  I'll
happily answer your questions, though.

-Jeff

On Mar 15, 2:42 pm, "Pedro Algarvio, aka, s0undt3ch" <u...@ufsoft.org>
wrote:
> On Mar 11, 2:13 pm, 一首诗 <newpt...@gmail.com> wrote:
>
>
>
> > Hi Jeff,
>
> > In my project I use the *model* to indicate an instance of Database.
> > I don't really need multiple instances of Database.  But when I wrote
> > unit test, I always create an new one database in setup, which create
> > a new sqlite in memory database to avoid conflicts between test cases.
>
> > About the trick to make *sess* a keywork parameter,  that's really
> > clever!
> > Thanks a lot!
>
> > On Mar 11, 9:05 pm, Jeff FW <jeff...@gmail.com> wrote:
>
> > > Logging SA objects *after* the session is gone will always be a
> > > problem, unless you make sure to detach all of them from the session.
> > > I'd just log the original request, instead.  In my case, I have to
> > > convert all of my SA objects to something Perspective Broker
> > > understands, so I actually log those *after* that, as they're no
> > > longer part of the session--but I'm not sure if you can do that in
> > > your case.
>
> > > As for the decorator--I got a little confused with your names--you
> > > call it "model" in your decorator, but it's really an instance of
> > > Database when it gets passed in as "self".  One way to get rid of that
> > > parameter would be to make sess a keyword argument, like so:
>
> > >     def wrapper(*args, **kw):
> > >         sess = model.Session()
> > >         try:
> > >             return f(sess=sess, *args, **kw)
>
> > > and then change your method:
>
> > >     def _getObjectById(self, klass, id, sess=None):
> > >         return sess.query(klass).get(id)
>
> > > That way, "self" will get passed in *args with no problem.
>
> > > Are you planning to have multiple instances of your Database class?
> > > If not, I'd suggest changing everything in it into class methods, so
> > > that way you can call it *without* an instance at all, and don't have
> > > to worry about connecting to the database multiple times by accident.
> > > Just a thought.
>
> > > -Jeff
>
> > > On Mar 10, 10:38 am, 一首诗 <newpt...@gmail.com> wrote:
>
> > > > Hi Jeff,
>
> > > > Thanks for your kind suggestion.
>
> > > > I first add some log decorators, but i found when it might cause to
> > > > print sqalchemy objects which has not been bound to any session.
>
> > > > And I am not quite sure about how to make the decorator mor genreal.
>
> > > > Actually, I think I must use model as the first parameter because as a
> > > > instance method, "_getObjectById" require the first parameter to be
> > > > "self".
> > > > Can you write a few lines of code to show your suggestion?
>
> > > > On Mar 8, 5:06 am, Jeff FW <jeff...@gmail.com> wrote:
>
> > > > > That's pretty similar to what I do, actually, if a bit simpler (but
> > > > > that's good!)  One suggestion would be to throw an except (maybe for
> > > > > the base SQLAlchemy exception class)  in your try block, otherwise you
> > > > > run the risk of things dying in an ugly way.  I'm not familiar with
> > > > > pyamf, so I don't know how it would handle errors, but twisted usually
> > > > > carries on as if nothing happens.
>
> > > > > Also, I'd make the decorator a bit more general--don't put the model
> > > > > argument in wrapper().  Put sess first, then take *args and **kwargs,
> > > > > and pass those right to the inner function f(). That way you can reuse
> > > > > it for anything that requires a DB session.
>
> > > > > Other things you could add (if so inclined) are decorators for logging
> > > > > and other types of error handling (like catching IntegrityErros thrown
> > > > > by duplicates.)  I do those things, but I might be a bit OCD :-)
>
> > > > > -Jeff
>
> > > > > On Mar 7, 1:41 am, 一首诗 <newpt...@gmail.com> wrote:
>
> > > > > > Hi, Thanks for your reply.  I'm using it the way like you.  The only
> > > > > > difference is that I am using pyamf instead of PB.
>
> > > > > > On every request, I delegate required db operations to a class 
> > > > > > called
> > > > > > Database, similar to these code below.
>
> > > > > > I used to use scope_session instead of create and close session 
> > > > > > every
> > > > > > time.   But as I said in my earlier mails, they don't work.
>
> > > > > > These code below seems to work right now.  But if you have more
> > > > > > suggestion,  I will be very thankful.
>
> > > > > > #=========================================
>
> > > > > > def require_session(f):
> > > > > >     '''create and close session for each synchronous method'''
> > > > > >     def wrapper(model, *args, **kw):
> > > > > >         sess = model.Session()
> > > > > >         try:
> > > > > >             return f(model, sess, *args, **kw)
> > > > > >         finally:
> > > > > >             sess.close()
> > > > > >     return wrapper
>
> > > > > > class Database()
> > > > > >     def __init__(self, conn_str):
> > > > > >         self.conn_str = conn_str
> > > > > >         self.engine = create_engine(self.conn_str, echo=False)
> > > > > >         self.Session = sessionmaker(bind = self.engine,
> > > > > > expire_on_commit=False)
>
> > > > > >     def getObjectById(self, klass, id):
> > > > > >         return threads.deferToThread(self._getObjectById, klass, id)
>
> > > > > >     @require_session
>
> > > > > >     def _getObjectById(self, sess, klass, id):
>
> > > > > >         return sess.query(klass).get(id)
> > > > > > #=========================================
>
> > > > > > On Mar 6, 5:44 am, Jeff FW <jeff...@gmail.com> wrote:
>
> > > > > > > Don't use scoped_session--you'll run into problems no matter what 
> > > > > > > you
> > > > > > > do.  I'm using Perspective Broker from Twisted with SQLAlchemy.  I
> > > > > > > make sure to create and commit/rollback a session for *every* PB
> > > > > > > request.  It works perfectly, and that's the only way I was really
> > > > > > > able to get it to work in all cases.
>
> > > > > > > Assuming you're using Twisted in a similar way, you could write a
> > > > > > > simple decorator to wrap any functions that need a database 
> > > > > > > session in
> > > > > > > the begin/commit stuff as necessary.
>
> > > > > > > If you can give more details of how you're using Twisted, I might 
> > > > > > > be
> > > > > > > able to offer some more insight.
>
> > > > > > > -Jeff
>
> > > > > > > On Mar 5, 12:33 am, 一首诗 <newpt...@gmail.com> wrote:
>
> > > > > > > > I'm not quite sure, but I think I'm pretty careful of sharing 
> > > > > > > > objects
> > > > > > > > between threads.
>
> > > > > > > > 1st, I only cached as few as possible orm objects.  I tried to 
> > > > > > > > detach
> > > > > > > > them, but I found that if I detach them,  I can't access any of 
> > > > > > > > their
> > > > > > > > fields any more.
>
> > > > > > > > 2nd, I create new orm objects based on client request, pass 
> > > > > > > > them to
> > > > > > > > class Database and then merge them to scoped sessions, change, 
> > > > > > > > commit
> > > > > > > > and then discard these objects.
>
> > > > > > > > 3rd, I switch to sqlite frequently to check if there is any 
> > > > > > > > database
> > > > > > > > operation outside Database, because sqlite doesn't allow 
> > > > > > > > multi-thread
> > > > > > > > access.
>
> > > > > > > > Actually it seems to work until 2 or 3 days ago suddenly cases 
> > > > > > > > hang
> > > > > > > > the server.
>
> > > > > > > > Ah, as I've already written lots of code in ORM, I think maybe I
> > > > > > > > should try to change Database to use a dedicated thread to 
> > > > > > > > handle all
> > > > > > > > database operations.
>
> > > > > > > > That might be a bottle neck of my application, but I really 
> > > > > > > > can't give
> > > > > > > > up orm as these mapper classes are used everywhere in my 
> > > > > > > > application.
>
> > > > > > > > On Mar 4, 7:26 pm, 一首诗 <newpt...@gmail.com> wrote:
>
> > > > > > > > > Hi, all
>
> > > > > > > > > I am using sqlalchemy in twisted in my project in the way 
> > > > > > > > > below.
> > > > > > > > > Defer any database operation so the twisted's main thread 
> > > > > > > > > won't be
> > > > > > > > > blocked.
>
> > > > > > > > > And I use scoped_session, so that sessions won't have to be 
> > > > > > > > > created
> > > > > > > > > again and again.
>
> > > > > > > > > ======================================
> > > > > > > > > class Database()
> > > > > > > > >     def __init__(self, conn_str):
> > > > > > > > >         self.conn_str = conn_str
> > > > > > > > >         self.engine = create_engine(self.conn_str, echo=False)
> > > > > > > > >         self.Session = scoped_session(sessionmaker(bind = 
> > > > > > > > > self.engine,
> > > > > > > > >              expire_on_commit=False))
>
> > > > > > > > >     def getObjectById(self, klass, id):
> > > > > > > > >         return threads.deferToThread(self._getObjectById, 
> > > > > > > > > klass, id)
>
> > > > > > > > >     def _getObjectById(self, klass, id):
> > > > > > > > >         sess = self.Session()
> > > > > > > > >         return sess.query(klass).get(id)
> > > > > > > > > ======================================
>
> > > > > > > > > The code doesn't work.   When I limit the thread numbers to 1
>
> > > > > > > > >     reactor.suggestThreadPoolSize(1)
>
> > > > > > > > > Everything goes fine.  Other wise the server would be blocked 
> > > > > > > > > and must
> > > > > > > > > be killed by "kill 9 ...".
>
> > > > > > > > > The result conflicts with my understanding of sqlalchemy.  
> > > > > > > > > Since I
> > > > > > > > > don't share any object between threads, there should be no 
> > > > > > > > > problem!
>
> > > > > > > > > Ah....  It always have risk to use something you haven't tried
> > > > > > > > > before ....- Hide quoted text -
>
> > > > > - Show quoted text -
>
> Seems that I'm on the same spot as you guys are, I *want* to work with
> both sqlalchemy
> and twisted.
>
> 一首诗 uses a class, do you too Jeff?
>
> What about setting up the database model object classes? and mapping?
> Same as with non async SA code?
> By any chance do you guys have any public code on how you're doin'
> this?
> One always learns just by looking....
>
> Pedro Algarvio.
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"sqlalchemy" group.
To post to this group, send email to sqlalchemy@googlegroups.com
To unsubscribe from this group, send email to 
sqlalchemy+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to