I am using SQLAlchemy 0.5.5 which is the version packaged with Red Hat
Enterprise 6.  I am using the below class to implement transactions
using closures.  (I have excluded methods unrelated to this issue.)  I
am using psycopg2 2.0.13 ('postgres://' URLs) to talk to the database,
if that matters.

The difference between "working" and "not working" for me is this
difference in __init__.

Working:
    self._engine = sqlalchemy.create_engine(URL)
    self._session = sqlalchemy.orm.scoped_session(
        sqlalchemy.orm.sessionmaker(self._engine,
**self._set_compatibility(sqlalchemy.__version__)))

Not working:
    self._session =
sqlalchemy.orm.sessionmaker(**self._set_compatibility(sqlalchemy.__version__))
    self._engine = sqlalchemy.create_engine(URL)
    self._session.configure(bind=self._engine)

The problem is, if I pass poolclass=AssertionPool to create_engine, I
get an AssertionError exception after as few as three consecutive
transactions with the "non-working" code.  I have a single-threaded
process that does not use nested transactions and executes
transactions sequentially.

Basically my question is, is the observed behavior surprising, and if
not, what exactly is wrong with my "not working" code?  I'm not
certain that I really understand how sessions work.

"Working" code with portions removed that are not relevant to this
posting:

    import sqlalchemy.orm

    class SQLAlchemyDB:
      def _set_compatibility(self, version):
        major, minor = map(int, version.split('.'))[:2]
        if major > 0 or minor > 5:
          raise NotImplementedError, \
              'this module not tested against SQLAlchemy version %s' %
(version,)
        smargs = {'autoflush': True}
        if minor > 4:
          smargs['autocommit'] = False
          smargs['expire_on_commit'] = False  # no need to merge for
every transaction
        else: # version 0.4.x
          smargs['transactional'] = True
        return smargs

      def __init__(self, URL):
        self._engine = sqlalchemy.create_engine(URL)
        self._session =
sqlalchemy.orm.scoped_session(sqlalchemy.orm.sessionmaker(
            self._engine,
**self._set_compatibility(sqlalchemy.__version__)))
        self._metadata = sqlalchemy.MetaData(bind=self._engine)

      def named_table(self, tablename):
        return sqlalchemy.Table(tablename, self._metadata,
autoload=True)

      def bind_class(self, freeclass, table):
        sqlalchemy.orm.mapper(freeclass, table)

      def new_bound_class(self, table):
        class ORMClassPrototype(object): pass
        self.bind_class(ORMClassPrototype, table)
        return ORMClassPrototype

      def named_orm_class(self, name):
        return self.new_bound_class(self.named_table(name))

      def transaction(self, callback):
        session = self._session()
        if not hasattr(session, 'add'):  # compatibility with
SQLAlchemy 0.4.x
          session.add = session.save
        try:
          result = callback(session)
        except BaseException:
          session.rollback()
          raise
        else:
          session.commit()
        finally:
          session.close()
        return result


Below is my log file with application-specific information scrubbed
out (I enabled logging at level logging.INFO for logger
sqlalchemy.pool).  To get this log, I used the "non-working" code and
interactively triggered the same transaction function three times in a
row.  The transaction function calls the named_orm_class method and
uses session.query a few times.  No objects created by the transaction
function have living references (in application code) after it
returns.  Note that after I shut down my application it returns the
connection to the pool.  This does not happen in the "working"
version.


    2011-02-23 18:19:36 EST INFO Application starting up
    2011-02-23 18:19:36 EST INFO Created new connection <connection
object at 0x29e2590; dsn:

'dbname=xxxxxxx host=xxxxxx port=5432 user=xxxxxx password=xxxx',
closed: 0>
    2011-02-23 18:19:36 EST INFO Connection <connection object at
0x29e2590; dsn: 'dbname=xxxxxxx

host=xxxxxx port=5432 user=xxxxxx password=xxxx', closed: 0> checked
out from pool
    2011-02-23 18:19:36 EST INFO Connection <connection object at
0x29e2590; dsn: 'dbname=xxxxxxx

host=xxxxxx port=5432 user=xxxxxx password=xxxx', closed: 0> being
returned to pool
    2011-02-23 18:19:36 EST INFO Connection <connection object at
0x29e2590; dsn: 'dbname=xxxxxxx

host=xxxxxx port=5432 user=xxxxxx password=xxxx', closed: 0> checked
out from pool
    2011-02-23 18:19:36 EST INFO Connection <connection object at
0x29e2590; dsn: 'dbname=xxxxxxx

host=xxxxxx port=5432 user=xxxxxx password=xxxx', closed: 0> being
returned to pool
    2011-02-23 18:21:43 EST INFO Beginning transaction (from
application)
    2011-02-23 18:21:43 EST INFO Connection <connection object at
0x29e2590; dsn: 'dbname=xxxxxxx

host=xxxxxx port=5432 user=xxxxxx password=xxxx', closed: 0> checked
out from pool
    2011-02-23 18:21:43 EST INFO Connection <connection object at
0x29e2590; dsn: 'dbname=xxxxxxx

host=xxxxxx port=5432 user=xxxxxx password=xxxx', closed: 0> being
returned to pool
    2011-02-23 18:21:43 EST INFO Connection <connection object at
0x29e2590; dsn: 'dbname=xxxxxxx

host=xxxxxx port=5432 user=xxxxxx password=xxxx', closed: 0> checked
out from pool
    2011-02-23 18:21:43 EST INFO Connection <connection object at
0x29e2590; dsn: 'dbname=xxxxxxx

host=xxxxxx port=5432 user=xxxxxx password=xxxx', closed: 0> being
returned to pool
    2011-02-23 18:21:43 EST INFO Connection <connection object at
0x29e2590; dsn: 'dbname=xxxxxxx

host=xxxxxx port=5432 user=xxxxxx password=xxxx', closed: 0> checked
out from pool
    2011-02-23 18:21:43 EST INFO Connection <connection object at
0x29e2590; dsn: 'dbname=xxxxxxx

host=xxxxxx port=5432 user=xxxxxx password=xxxx', closed: 0> being
returned to pool
    2011-02-23 18:21:43 EST INFO Connection <connection object at
0x29e2590; dsn: 'dbname=xxxxxxx

host=xxxxxx port=5432 user=xxxxxx password=xxxx', closed: 0> checked
out from pool
    2011-02-23 18:21:43 EST INFO Connection <connection object at
0x29e2590; dsn: 'dbname=xxxxxxx

host=xxxxxx port=5432 user=xxxxxx password=xxxx', closed: 0> being
returned to pool
    2011-02-23 18:21:43 EST INFO Connection <connection object at
0x29e2590; dsn: 'dbname=xxxxxxx

host=xxxxxx port=5432 user=xxxxxx password=xxxx', closed: 0> checked
out from pool
    2011-02-23 18:21:43 EST INFO Connection <connection object at
0x29e2590; dsn: 'dbname=xxxxxxx

host=xxxxxx port=5432 user=xxxxxx password=xxxx', closed: 0> being
returned to pool
    2011-02-23 18:21:43 EST INFO Connection <connection object at
0x29e2590; dsn: 'dbname=xxxxxxx

host=xxxxxx port=5432 user=xxxxxx password=xxxx', closed: 0> checked
out from pool
    2011-02-23 18:21:43 EST INFO Connection <connection object at
0x29e2590; dsn: 'dbname=xxxxxxx

host=xxxxxx port=5432 user=xxxxxx password=xxxx', closed: 0> being
returned to pool
    2011-02-23 18:21:43 EST INFO Connection <connection object at
0x29e2590; dsn: 'dbname=xxxxxxx

host=xxxxxx port=5432 user=xxxxxx password=xxxx', closed: 0> checked
out from pool
    2011-02-23 18:21:43 EST INFO Connection <connection object at
0x29e2590; dsn: 'dbname=xxxxxxx

host=xxxxxx port=5432 user=xxxxxx password=xxxx', closed: 0> being
returned to pool
    2011-02-23 18:21:43 EST INFO Connection <connection object at
0x29e2590; dsn: 'dbname=xxxxxxx

host=xxxxxx port=5432 user=xxxxxx password=xxxx', closed: 0> checked
out from pool
    2011-02-23 18:21:44 EST INFO Completed transaction (from
application)
    2011-02-23 18:21:51 EST INFO Beginning transaction (from
application)
    2011-02-23 18:21:51 EST INFO Connection <connection object at
0x29e2590; dsn: 'dbname=xxxxxxx

host=xxxxxx port=5432 user=xxxxxx password=xxxx', closed: 0> being
returned to pool
    2011-02-23 18:21:51 EST INFO Connection <connection object at
0x29e2590; dsn: 'dbname=xxxxxxx

host=xxxxxx port=5432 user=xxxxxx password=xxxx', closed: 0> checked
out from pool
    2011-02-23 18:21:51 EST INFO Connection <connection object at
0x29e2590; dsn: 'dbname=xxxxxxx

host=xxxxxx port=5432 user=xxxxxx password=xxxx', closed: 0> being
returned to pool
    2011-02-23 18:21:51 EST INFO Connection <connection object at
0x29e2590; dsn: 'dbname=xxxxxxx

host=xxxxxx port=5432 user=xxxxxx password=xxxx', closed: 0> checked
out from pool
    2011-02-23 18:21:51 EST INFO Completed transaction (from
application)
    2011-02-23 18:22:06 EST INFO Beginning transaction (from
application)
    2011-02-23 18:22:06 EST ERROR AssertionError
    (snip)
    2011-02-23 18:22:06 EST ERROR   File "xxxxxx.py", line 88, in
transaction
    2011-02-23 18:22:06 EST ERROR     result = callback(session)
    2011-02-23 18:22:06 EST ERROR   File "xxxxxxx.py", line 208, in
txn
    2011-02-23 18:22:06 EST ERROR     .filter(xxxxxxx ==
xxxxxxxxx).one()
    2011-02-23 18:22:06 EST ERROR   File "/usr/lib/python2.6/site-
packages/sqlalchemy/orm/query.py", line

1252, in one
    2011-02-23 18:22:06 EST ERROR     ret = list(self[0:2])
    2011-02-23 18:22:06 EST ERROR   File "/usr/lib/python2.6/site-
packages/sqlalchemy/orm/query.py", line

1152, in __getitem__
    2011-02-23 18:22:06 EST ERROR     return list(res)
    2011-02-23 18:22:06 EST ERROR   File "/usr/lib/python2.6/site-
packages/sqlalchemy/orm/query.py", line

1292, in __iter__
    2011-02-23 18:22:06 EST ERROR     return
self._execute_and_instances(context)
    2011-02-23 18:22:06 EST ERROR   File "/usr/lib/python2.6/site-
packages/sqlalchemy/orm/query.py", line

1295, in _execute_and_instances
    2011-02-23 18:22:06 EST ERROR     result =
self.session.execute(querycontext.statement,

params=self._params, mapper=self._mapper_zero_or_none())
    2011-02-23 18:22:06 EST ERROR   File "/usr/lib/python2.6/site-
packages/sqlalchemy/orm/session.py",

line 754, in execute
    2011-02-23 18:22:06 EST ERROR     return self.__connection(engine,
close_with_result=True).execute(
    2011-02-23 18:22:06 EST ERROR   File "/usr/lib/python2.6/site-
packages/sqlalchemy/orm/session.py",

line 719, in __connection
    2011-02-23 18:22:06 EST ERROR     return
self.transaction._connection_for_bind(engine)
    2011-02-23 18:22:06 EST ERROR   File "/usr/lib/python2.6/site-
packages/sqlalchemy/orm/session.py",

line 329, in _connection_for_bind
    2011-02-23 18:22:06 EST ERROR     conn = bind.contextual_connect()
    2011-02-23 18:22:06 EST ERROR   File "/usr/lib/python2.6/site-
packages/sqlalchemy/engine/base.py",

line 1229, in contextual_connect
    2011-02-23 18:22:06 EST ERROR     return self.Connection(self,
self.pool.connect(),

close_with_result=close_with_result, **kwargs)
    2011-02-23 18:22:06 EST ERROR   File "/usr/lib/python2.6/site-
packages/sqlalchemy/pool.py", line 142,

in connect
    2011-02-23 18:22:06 EST ERROR     return
_ConnectionFairy(self).checkout()
    2011-02-23 18:22:06 EST ERROR   File "/usr/lib/python2.6/site-
packages/sqlalchemy/pool.py", line 304,

in __init__
    2011-02-23 18:22:06 EST ERROR     rec = self._connection_record =
pool.get()
    2011-02-23 18:22:06 EST ERROR   File "/usr/lib/python2.6/site-
packages/sqlalchemy/pool.py", line 161,

in get
    2011-02-23 18:22:06 EST ERROR     return self.do_get()
    2011-02-23 18:22:06 EST ERROR   File "/usr/lib/python2.6/site-
packages/sqlalchemy/pool.py", line 849,

in do_get
    2011-02-23 18:22:06 EST ERROR     assert self.connection is not
None
    2011-02-23 18:52:46 EST WARNING Application shutting down
    2011-02-23 18:52:46 EST INFO Connection <connection object at
0x29e2590; dsn: 'dbname=xxxxxxx

host=xxxxxx port=5432 user=xxxxxx password=xxxx', closed: 0> being
returned to pool

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