On Oct 10, 2013, at 8:57 PM, Iain Duncan <iainduncanli...@gmail.com> wrote:

> Seems like there are some variety of opinion on some stuff on the pyramid 
> list so I thought I'd come straight to the source. In Pyramid, I can attach a 
> server wide shared object to the registry which is created on server startup, 
> and I can specify a factory for making requests that creates the request 
> object, available as a local argument (*not* a thread local request import) 
> to all code. In the request object I can also add an end-of-life callback.
> 
> I've been using SQLAlchemy by:
> 
> - creating the engine and sessionmaker at startup time, stashing in the ZCA 
> registry
> - calling the session maker at the beginning of the request lifecycle and 
> then creating the session for that request and attaching to the request.
> - doing a cleanup at end of request
> 
> According to my (possibly flawed) understanding of the SA docs, this should 
> mean I do not need to use a scoped session maker.

that is correct.


> The session object never gets imported as a magic global thread local thing, 
> it's always explicitly passed in as an arg.

you can also link the two things together like this, not that you'd need to:

from pyramid.threadlocal import get_current_request
Session = scoped_session(sessionmaker(), scopefunc=get_current_request)

now you're only using Pyramid's thread local voodoo, none in SQLAlchemy.


> Am I correct in this? Is there any advantage in using a scoped session anyway?

I find plenty.   I'm usually concerned about code that needs to run outside the 
context of a web request, like background jobs and utilities - this code still 
makes full use of the web app's model and all, just not the "request".    So 
without Pyramid's hook for session creation, someone else has to establish the 
new Session.   ScopedSession is nice because nobody has to tag themselves as 
the "creator" of the Session, it just creates the new Session as soon as 
someone starts using it.

Also having to pass a session around to all methods and functions that aren't 
web-request-aware can become burdensome.  My app over here actually has three 
different sessions for different use cases, so I guess if I weren't using 
scoped sessions I'd need to create some more substantial context object that I 
pass around to all these methods which has all three sessions, but then I'd 
need to reconcile that context object with Pyramid's request also.    Or 
perhaps, you can just make Pyramid's "request" the context itself and when 
you're running in a non-web context just use DummyRequest or something, but 
doesn't that seem strange/weird also?   Model objects that have nothing to do 
with web requests all have to become hardcoded to the concept of a "request", 
that seems no less distasteful than thread locals to me.

With a scoped session, none of these decisions even need to be made, you don't 
have to pass anything around to your model, the model has a place to get its 
context for database connectivity just like it has a place to get context for 
anything else it needs.  There's no downside to scoped sessions that I've 
observed and the Pyramid community's aversion to thread local "voodoo" IMHO is 
slightly misplaced.  Thread locals are, like so many other things, easy to 
misuse, particularly when random bits of code use them to communicate state and 
such.  But having a few well-located and globally accessible registries that 
are specific to your application, not a problem at all.  I see no evidence for 
Pyramid's assertion that they decrease testability, it's standard practice to 
patch well-known globals for testing, and in fact "mock.patch" is part of the 
Python standard library now.



Attachment: signature.asc
Description: Message signed with OpenPGP using GPGMail

Reply via email to