Java's InheritableThreadLocal equivalent in Python

Viewed 159

Is there any equivalent to Java's InheritableThreadLocal?
The idea is to have a deep copy of parent's thread threading.local dictionary in child thread.

1 Answers

I made a simple implementation.

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import copy
from _threading_local import local
from threading import current_thread, Thread


class InheritableThread(Thread):
    def __init__(self, *args, **kwargs):
        self.parent = current_thread()
        Thread.__init__(self, *args, **kwargs)


def copy_parent_attribute(self):
    """
    :raise AttributeError: parent may not exist
    """

    parent = current_thread().parent
    parent_local = self._local__impl.dicts.get(id(parent))
    if parent_local is not None:
        parent_dicts = parent_local[1]
        for key, value in parent_dicts.items():
            self.__setattr__(key, copy.deepcopy(value))


class InheritableLocal(local):
    """
    Please use InheritableThread to create threads, if you want your son threads can inherit parent threads' local
    """

    def __new__(cls, *args, **kwargs):
        self = local.__new__(cls, *args, **kwargs)
        try:
            copy_parent_attribute(self)
        except AttributeError:
            # Some threads may not be created by InheritableThread
            pass
        return self

    def __getattribute__(self, item):
        try:
            return local.__getattribute__(self, item)
        except AttributeError as e:
            try:
                copy_parent_attribute(self)
                return local.__getattribute__(self, item)
            except AttributeError:
                raise e

    def __delattr__(self, item):
        try:
            return local.__delattr__(self, item)
        except AttributeError as e:
            try:
                copy_parent_attribute(self)
                return local.__delattr__(self, item)
            except AttributeError:
                raise e

You can use it like this:

thread_ctx = InheritableLocal()
t = InheritableThread(target=function, args=(arg1, arg2, arg3))
t.start()
t.join()
Related