Your ads will be inserted here by
Easy AdSense.
Please go to the plugin admin page to
Paste your ad code OR
Suppress this ad slot.
No here’s a nice way to shoot yourself in the foot with Python tuples. We all know Python tuples are constructed by commas, not round brackets. So
>>> 1,2,3,4 (1, 2, 3, 4) |
but
>>> (1) 1 |
Most important
>>> 1, (1,) |
Those differences are subtle, but significant. So keep that in mind when working on something larger that just insists on breaking up and hurling insults at you and you would never suspect that you have made such a trivial mistake.
In my case I was trying to instantiate an SQLAlchemy scoped Session
object in one module and trying to bind an engine to it in the initialization code of my app. The reason for this is to make it possible to easily exchange the engine object, in particular for unit tests, that should typically operate on a separate test database or in memory database. What I did was
Your ads will be inserted here by
Easy AdSense.
Please go to the plugin admin page to
Paste your ad code OR
Suppress this ad slot.
# core/db_session.py from sqlalchemy.orm import scoped_session, sessionmaker session_factory = sessionmaker(autocommit=False, autoflush=False,) db_session = scoped_session(session_factory) # runserver.py from core.app import settings, app from sqlalchemy import create_engine from core.db_session import db_session db_engine = create_engine('sqlite:////tmp/cc.sqlite', convert_unicode=True), db_session.configure(bind=db_engine) from werkzeug.serving import run_simple if __name__ == '__main__': run_simple('127.0.0.1', 5000, app, use_debugger=True, use_reloader=True) |
roughly following the SQLAlchemy documentation.
Werkzeugs excellent debugging tool gave me an impressive stack trace, telling me something about tuples having no “contextual context”. Now I know I should have seen the elephant in the room, but I was so immersed in thread locals and Werkzeug Local, LocalManagers and LocalStacks that I was almost 100% positive I was experiencing some major scoping issue. So I spent half the morning trying various different approaches of rearranging my code, thinking up hacky ways to monkeypatch (yes, I was that desperate) the way the db_session was fed into my BaseModel class.
Buuuuut… the solution was so simple. Instead of
db_engine = create_engine('sqlite:////tmp/cc.sqlite', convert_unicode=True), |
I simply had to write
db_engine = create_engine('sqlite:////tmp/cc.sqlite', convert_unicode=True) |
I wonder how that comma wound up there in the first place…
Leave a Reply