Async SQLAlchemy: TypeError: cannot pickle 'module' object
Maksim-Burtsev opened this issue · 1 comments
Maksim-Burtsev commented
I use https://github.com/ets-labs/python-dependency-injector/tree/master/examples/miniapps/fastapi-sqlalchemy as example for use DI in project with fastAPI + sqlalchemy (async), but when i try to start webapp i have this error:
line 22, in <module>
container = Container()
^^^^^^^^^^^
File "src/dependency_injector/containers.pyx", line 730, in dependency_injector.containers.DeclarativeContainer.__new__
File "src/dependency_injector/providers.pyx", line 4913, in dependency_injector.providers.deepcopy
File "src/dependency_injector/providers.pyx", line 4920, in dependency_injector.providers.deepcopy
File "/opt/homebrew/Cellar/python@3.11/3.11.5/Frameworks/Python.framework/Versions/3.11/lib/python3.11/copy.py", line 145, in deepcopy
y = copier(x, memo)
^^^^^^^^^^^^^^^
File "/opt/homebrew/Cellar/python@3.11/3.11.5/Frameworks/Python.framework/Versions/3.11/lib/python3.11/copy.py", line 230, in _deepcopy_dict
y[deepcopy(key, memo)] = deepcopy(value, memo)
^^^^^^^^^^^^^^^^^^^^^
File "/opt/homebrew/Cellar/python@3.11/3.11.5/Frameworks/Python.framework/Versions/3.11/lib/python3.11/copy.py", line 152, in deepcopy
y = copier(memo)
^^^^^^^^^^^^
File "src/dependency_injector/providers.pyx", line 2536, in dependency_injector.providers.Factory.__deepcopy__
File "src/dependency_injector/providers.pyx", line 4920, in dependency_injector.providers.deepcopy
File "/opt/homebrew/Cellar/python@3.11/3.11.5/Frameworks/Python.framework/Versions/3.11/lib/python3.11/copy.py", line 145, in deepcopy
y = copier(x, memo)
^^^^^^^^^^^^^^^
File "/opt/homebrew/Cellar/python@3.11/3.11.5/Frameworks/Python.framework/Versions/3.11/lib/python3.11/copy.py", line 230, in _deepcopy_dict
y[deepcopy(key, memo)] = deepcopy(value, memo)
^^^^^^^^^^^^^^^^^^^^^
File "/opt/homebrew/Cellar/python@3.11/3.11.5/Frameworks/Python.framework/Versions/3.11/lib/python3.11/copy.py", line 160, in deepcopy
rv = reductor(4)
^^^^^^^^^^^
TypeError: cannot pickle 'module' object
I have some differences instead of example:
my database.py
import logging
from sqlalchemy.ext.asyncio import async_sessionmaker, create_async_engine
from sqlalchemy.orm import declarative_base
from settings import settings
logger = logging.getLogger(__name__)
Base = declarative_base()
class Database:
def __init__(self) -> None:
self.engine = create_async_engine(settings.get_pg_url(), pool_size=100,)
self.session_maker = async_sessionmaker(self.engine, expire_on_commit=False,)
my container.py
:
"""Containers module."""
from dependency_injector import containers, providers
from database import Database
from services import *
from infrastructure.repositories import *
class Container(containers.DeclarativeContainer):
db = providers.Singleton(Database)
# repositories
foo_repo = providers.Factory(
FooRepository,
session_factory=db.provided.session_maker,
)
...
#services
foo_service = providers.Factory(
FooService,
repo=foo_repo,
)
...
and with app creation i have
container = Container()
db = container.db()
app.container: Container = container
app.container.wire(
[
"src.routers",
"src.services",
]
)
What this error means and how can i fix it?
(python 3.11)
Maksim-Burtsev commented
I found the way to make it work
I hope this will help those who face the same error:
container.py
from dependency_injector import containers, providers
from dependency_injector import containers, providers
from sqlalchemy import orm
from sqlalchemy.ext.asyncio import AsyncSession, create_async_engine
from infrastructure.repositories import *
from services import *
class Container(containers.DeclarativeContainer):
# db
engine = providers.Singleton(
create_async_engine,
DATABASE_URL,
pool_size=100,
)
async_session = providers.Factory(
orm.sessionmaker,
bind=engine,
class_=AsyncSession,
expire_on_commit=False,
)
# repositories
foo_repo = providers.Factory(
FooRepository,
session=async_session,
)
...
#services
foo_service = providers.Singleton(
FooService,
repo=foo_repo,
)
...
with app creation:
app.container: Container = Container()
app.container.wire(
[
"routers.foo_router",
...
]
and now everything works in routers/foo_router.py
:
@router.get(
"/",
response_model=list[FooSchema],
)
@inject
async def get_foos(
foo_service: FooService = Depends(Provide[Container.foo_service]),
) -> list[FooModel]:
return await foo_service.get_objects()