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 [email protected].
To unsubscribe from this group, send email to
[email protected].
For more options, visit this group at
http://groups.google.com/group/sqlalchemy?hl=en.