Search code examples
pythonmultithreadingmodulelocal

python threading.local() in different module


I am trying to pass data in threading.local() to functions in different module. Code is something like this:

other_module.py:

import threading

# 2.1  
ll = threading.local()

def other_fn():

 # 2.2    
 ll = threading.local()

 v = getattr(ll, "v", None)
 print(v)

main_module.py:

import threading
import other_module

# 1.1
ll = threading.local()

def main_fn(v):

 # 1.2
 ll = threading.local()

 ll.v = v
 other_fn()


for i in [1,2]:
 t = threading.Thread(target=main_fn, args=(i,))
 t.start()

But none of combinations 1.x - 2.x not working for me. I have found similar question - Access thread local object in different module - Python but reply, marked as answer not working for me too if print_message function located in different module.

Is it possible to pass thread local data between modules without passing it as function argument?


Solution

  • In a similar situation I ended up doing the following in a separate module:

    import threading
    from collections import defaultdict
    
    tls = defaultdict(dict)
    
    
    def get_thread_ctx():
        """ Get thread-local, global context"""
        return tls[threading.get_ident()]
    

    This essentially creates a global variable called tls. Then each thread (based on its identity) gets a key in the global dict. I handle that also as a dict. Example:

    class Test(Thread):
        def __init__(self):
            super().__init__()
            # note: we cannot initialize thread local here, since thread 
            # is not running yet
    
        def run(self):
            # Get thread context
            tmp = get_thread_ctx()
            # Create an app-specific entry
            tmp["probe"] = {}
            self.ctx = tmp["probe"]
    
            while True:
                ...
    

    Now, in a different module:

    def get_thread_settings():
        ctx = get_thread_ctx()
        probe_ctx = ctx.get("probe", None)
    
        # Get what you need from the app-specific region of this thread
        return probe_ctx.get("settings", {})
    

    Hope it helps the next one looking for something similar