python-dependency-injector icon indicating copy to clipboard operation
python-dependency-injector copied to clipboard

Unable to initialize instance that are picklable in the container

Open arunbalasubramani opened this issue 2 years ago • 2 comments
trafficstars

Getting the following error while initializing the container that contains instances that cannot be pickled. Is there a requirement that all the instances created within the container should be picklable?

Version used: 4.41.0

class DependencyContainer(containers.DeclarativeContainer):
    metric_flow_client = providers.Singleton(
        MetricFlowClient,
        sql_client=SnowflakeSqlClient.from_config(mf_snowflake_config)
    )

if __name__ == "__main__":
    container = DependencyContainer().   <---- Fails here
    container.init_resources()
    container.wire(modules=[__name__])

Error log:

Traceback (most recent call last):
  File "/Users/arunkumar/Projects/unified-metrics-platform/consumption_grpc/grpc_server.py", line 79, in <module>
    container = DependencyContainer()
  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 "/Users/arunkumar/.pyenv/versions/3.9.10/lib/python3.9/copy.py", line 146, in deepcopy
    y = copier(x, memo)
  File "/Users/arunkumar/.pyenv/versions/3.9.10/lib/python3.9/copy.py", line 230, in _deepcopy_dict
    y[deepcopy(key, memo)] = deepcopy(value, memo)
  File "/Users/arunkumar/.pyenv/versions/3.9.10/lib/python3.9/copy.py", line 153, in deepcopy
    y = copier(memo)
  File "src/dependency_injector/providers.pyx", line 2835, in dependency_injector.providers.BaseSingleton.__deepcopy__
  File "src/dependency_injector/providers.pyx", line 4920, in dependency_injector.providers.deepcopy
  File "/Users/arunkumar/.pyenv/versions/3.9.10/lib/python3.9/copy.py", line 146, in deepcopy
    y = copier(x, memo)
  File "/Users/arunkumar/.pyenv/versions/3.9.10/lib/python3.9/copy.py", line 230, in _deepcopy_dict
    y[deepcopy(key, memo)] = deepcopy(value, memo)
  File "/Users/arunkumar/.pyenv/versions/3.9.10/lib/python3.9/copy.py", line 172, in deepcopy
    y = _reconstruct(x, memo, *rv)
  File "/Users/arunkumar/.pyenv/versions/3.9.10/lib/python3.9/copy.py", line 270, in _reconstruct
    state = deepcopy(state, memo)
  File "/Users/arunkumar/.pyenv/versions/3.9.10/lib/python3.9/copy.py", line 146, in deepcopy
    y = copier(x, memo)
  File "/Users/arunkumar/.pyenv/versions/3.9.10/lib/python3.9/copy.py", line 230, in _deepcopy_dict
    y[deepcopy(key, memo)] = deepcopy(value, memo)
  File "/Users/arunkumar/.pyenv/versions/3.9.10/lib/python3.9/copy.py", line 161, in deepcopy
    rv = reductor(4)
TypeError: cannot pickle '_thread.lock' object

Thanks for the help!

arunbalasubramani avatar Aug 03 '23 18:08 arunbalasubramani

I've had the same problem, but with pymongo's Collection class. Ended up using providers.Callable and wrapping the object creation in a function, as they are picklable:

from dependency_injector import containers, providers
from pymongo.collection import Collection

MONGO_DATABASE = ...
COLLECTION_NAME = ...


class FooRepository:
    pass


def _create_collection():
    return Collection(
        database=MONGO_DATABASE,
        name=COLLECTION_NAME,
    )


class FooContainer(containers.DeclarativeContainer):
    foo_repository = providers.Factory(
        FooRepository,
        collection=providers.Callable(_create_collection),
    )

It's not an ideal solution, but I hope it helps!

Nefendi avatar Sep 25 '23 10:09 Nefendi