question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Using "configure" on scoped_session does not bind engine properly

See original GitHub issue

Migrated issue, originally created by Adam Olsen (@synic)

Using SQLAlchemy 1.1.9 (though it happened with 1.1.8 too) with Python 2.7.13 on OS X

Using scoped_session.configure to change the engine doesn’t bind the engine properly. For instance, if you do something like this:

session = orm.scoped_session(orm.sessionmaker())
engine = create_engine('sqlite://')
session.configure(bind=engine)
session.close_all()

engine = create_engine('postgresql://someuser:somepass@localhost:5432/db',
    json_serializer=serialize, json_deserializer=deserialize)
session.configure(bind=engine)

print session.bind  # will output `Engine(sqlite://)`

It results in errors such as the one you see below (if you start with sqlite, but then switch to postgres and try to query tables).

If you’re wondering WHY we would want to do this, it is for testing. Our test suite tries to make sure that everything works ok with both sqlite and postgresql. We can’t just create a new instance of the scoped_session, as it will break the factories and various other places that call for a session at load time (we could probably find some way to make it work with two different sessions, but I don’t want to do that unless I have to).

Traceback (most recent call last):
  File "/vagrant/apps/skedup/tests/base.py", line 28, in setUp
    db.session.commit()
  File "/usr/local/lib/python2.7/site-packages/sqlalchemy/orm/scoping.py", line 157, in do
    return getattr(self.registry(), name)(*args, **kwargs)
  File "/usr/local/lib/python2.7/site-packages/sqlalchemy/orm/session.py", line 874, in commit
    self.transaction.commit()
  File "/usr/local/lib/python2.7/site-packages/sqlalchemy/orm/session.py", line 459, in commit
    self._assert_active(prepared_ok=True)
  File "/usr/local/lib/python2.7/site-packages/sqlalchemy/orm/session.py", line 276, in _assert_active
    % self._rollback_exception
InvalidRequestError: This Session's transaction has been rolled back due to a previous exception during flush. To begin a new transaction with this Session, first issue Session.rollback(). Original exception was: (exceptions.AttributeError) 'SQLiteDialect_pysqlite' object has no attribute '_json_serializer'

Doing something like this totally fixes it (manually assigning the engine to session.bind), but it seems like it shouldn’t be required:

session = orm.scoped_session(orm.sessionmaker())
engine = create_engine('sqlite://')
session.configure(bind=engine)
session.close_all()

engine = create_engine('postgresql://someuser:somepass@localhost:5432/db',
    json_serializer=serialize, json_deserializer=deserialize)
session.configure(bind=engine)
session.bind = engine  # <---- this is the key to making it work

print session.bind  # will output `Engine(postgresql://someuser:somepass@localhost:5432/db)`

Issue Analytics

  • State:closed
  • Created 6 years ago
  • Comments:6

github_iconTop GitHub Comments

1reaction
sqlalchemy-botcommented, Nov 27, 2018

Michael Bayer (@zzzeek) wrote:

Your test as written does produce the correct output, because you are not actually instantiating the session:

from sqlalchemy import orm, create_engine

session = orm.scoped_session(orm.sessionmaker())
engine = create_engine('sqlite://')
session.configure(bind=engine)
session.close_all()

engine = create_engine('postgresql://someuser:somepass@localhost:5432/db')
session.configure(bind=engine)

print session.bind

output:

Engine(postgresql://someuser:***@localhost:5432/db)

the issue you’re having is that you are instantiating a session first, then changing the “bind” on the sessionmaker that produces a new session:

from sqlalchemy import orm, create_engine

session = orm.scoped_session(orm.sessionmaker())
engine = create_engine('sqlite://')
session.configure(bind=engine)
session.connection()
session.close_all()

engine = create_engine('postgresql://someuser:somepass@localhost:5432/db')
session.configure(bind=engine)

print session.bind

in the output, there is in fact a handy warning as well telling you as much:

#!


python test.py 
/home/classic/dev/sqlalchemy/lib/sqlalchemy/orm/scoping.py:106: SAWarning: At least one scoped session is already present.  configure() can not affect sessions that have already been created.
  warn('At least one scoped session is already present. '
Engine(sqlite://)

the solution is to remove the session that’s instantiated:

from sqlalchemy import orm, create_engine

session = orm.scoped_session(orm.sessionmaker())
engine = create_engine('sqlite://')
session.configure(bind=engine)
session.connection()
session.remove()

engine = create_engine('postgresql://someuser:somepass@localhost:5432/db')
session.configure(bind=engine)

print session.bind

assuming things are the same on your end, there’s no bug here, please confirm thanks!

0reactions
sqlalchemy-botcommented, Nov 27, 2018

Changes by Adam Olsen (@synic):

  • changed status to closed
Read more comments on GitHub >

github_iconTop Results From Across the Web

Using "configure" on scoped_session does not bind engine ...
Using scoped_session.configure to change the engine doesn't bind the engine properly. For instance, if you do something like this: session ...
Read more >
SAWarning: At least one scoped session is already present
You should use one scope session binding your models to different database engines instead.
Read more >
Functional test warning when app uses SQLAlchemy ... - GitHub
Anonymous: I'm getting the following warning: SAWarning: At least one scoped session is already present. configure() can not affect sessions ...
Read more >
Contextual/Thread-local Sessions — SQLAlchemy 2.0 ...
Callers who call upon the registry in a different thread get a Session instance that is local to that other thread.
Read more >
UnboundExecutionError gotcha when working with ...
Session.configure(bind=engine), none of the Sessions you create will be properly bound to ... from sqlalchemy.orm import scoped_session, sessionmaker engine ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found