1

I have a method which retrieves kwargs and future. I would like to save a dictionary of kwargs to future for later processing future result with kwargs.

class ThreadPoolExecutorImproved(object):

def __init__(self, max_workers):
    self._executor = ThreadPoolExecutor(max_workers)
    self._futures = {}

def __enter__(self):
    return self

def __exit__(self, exc_type, exc_val, exc_tb):
    kwargs_to_exception = {}
    for kwargs, future in self._futures.iteritems():
        if future.exception():
            kwargs_to_exception[kwargs] = future.exception

    if kwargs_to_exception:
        raise ThreadPoolException(kwargs_to_exception)

def submit(self, fn, *args, **kwargs):
    future = self._executor.submit(fn, *args, **kwargs)
    key = tuple(kwargs.items())
    self._futures[key] = future
    return future

However, I get an error on the line self.futures[key] = future:

TypeError: unhashable type: 'dict' for python

why is it? I created a tuple from kwargs!

9
  • 2
    It means you have a dictionary in one of the values of kwargs. Commented Apr 5, 2017 at 13:17
  • I got it. so I would need each value to wrap it with a tuple?
    – Dejell
    Commented Apr 5, 2017 at 13:18
  • you can indeed convert every dictionary to a tuple equivalent. Note that you will have to do this recursively since these dictionaries can also contain dictionaries and so on. Commented Apr 5, 2017 at 13:19
  • 1
    not that it is possible that the values are also unhashable types other than dictionaries (like lists or a generic object). So the problem is rather hard to solve in general, since it is not said these have hashable counterparts. Commented Apr 5, 2017 at 13:21
  • 1
    BTW, why are you using kwargs as the key in the first place? What if two functions are called with the same kwargs, or what if kwargs is empty?
    – tobias_k
    Commented Apr 5, 2017 at 13:24

1 Answer 1

1

The typical workaround for this situation is to use future as a key; Your code

key = tuple(kwargs.items())
self._futures[key] = future

Migrate to

self._futures[future] = tuple(kwargs.items())

And when you want to process self._futures, you can just iterate this

for future, kw in self._futures:
    # check kw
    # do your stuff

Not the answer you're looking for? Browse other questions tagged or ask your own question.