RazerM/sqlalchemy_aio

[resolved] question about reflection

massimiliano-della-rovere opened this issue · 4 comments

Is there a way to use sqlalchemy_aio with:

  • MetaData(...).reflect()
  • Table(..., autoload=True, extend_existing=True) ?

These functions are directly called, so I am not able to await for the engine.

Modern SQLAlchemy doesn't emphasise bound metadata, so it should be explicit when you need to pass the engine. You can get the actual engine using engine._engine:

metadata = MetaData(...)
metadata.reflect(bind=engine._engine)

...


table = Table(..., autoload_with=engine._engine, extend_existing=True)

These will block, so you can run them within an executor, something like this:

def blocking_fn():
    metadata.reflect(bind=engine._engine)

loop = asyncio.get_event_loop()
loop.run_in_executor(None, blocking_fn)

Thank you, this solves my problem.

Your answer could be copied in the Wiki/FAQ.

Yeah, Table(..., metadata, autoload_with=True) style reflection was the first thing I tried with sqlalchemy_aio and it failed with a quite obscure exception stacktrace - ending in:

File "/usr/lib64/python3.6/site-packages/sqlalchemy/sql/schema.py", line 524, in _autoload
    autoload_with.run_callable(
AttributeError: 'AsyncioEngine' object has no attribute 'run_callable'

I can confirm, explictly specifying engine._engine resolves this.

Since sqlalchemy refelction is a popular feature it probably makes sense to add a note regarding this usage into the README.

And perhaps it's even possible to hook somewhere into sqlalchemy to produce a more developer friendly error message in case one forgets to explicitly specify engine._engine.

@gsauthof See #10 for a possible solution.