Mar-09-2021, 12:13 PM
I have a factory method that may be called from many threads. The method looks inside the thread locals for a certain object and if it doesn't exist, creates one and stores it in thread locals and then returns the same.
The object created thus has a __del__ method implemented for cleanup.
Here is a small code that explains what I am doing . My expectation is that, there are only two objects created by the factory one in main thread and other in the daemon thread.
I also created a stackoverflow post but haven't got any answers yet.
The object created thus has a __del__ method implemented for cleanup.
Here is a small code that explains what I am doing . My expectation is that, there are only two objects created by the factory one in main thread and other in the daemon thread.
#!/usr/bin/env python3 # -*- coding: utf-8 -*- import time import threading class MysteryObject: def __init__(self, name): self.name = name def __del__(self): print('{} => {} destroyed'.format(self.__class__.__name__, self.name)) def get_thread_ident(): current = threading.currentThread() return '_'.join([current.getName(), str(current.ident)]) def make_object(): thread_ident = get_thread_ident() thread_locals = threading.local() if hasattr(thread_locals, 'mystery_object'): print('found mystery object in thread {}'.format(thread_ident)) return thread_locals.mystery_object print('Creating mystery object in thread {}'.format(thread_ident)) thread_locals.mystery_object = MysteryObject(thread_ident) return thread_locals.mystery_object def test_threaded_object_maker(total_iteration): iteration = 0 my_obj = make_object() while iteration < total_iteration: my_cur_obj = make_object() if id(my_cur_obj) != id(my_obj): print('{} Thread mystery object was GCed'.format(my_obj.name)) my_obj = my_cur_obj time.sleep(2) iteration += 2 def test_object_maker_main(): main_thread_mystery = make_object() threads = [] for _ in range(1): threads.append(threading.Thread(target=test_threaded_object_maker, args=(5,))) threads[-1].start() for th in threads: th.join() main_thread_mystery2 = make_object() if id(main_thread_mystery) != id(main_thread_mystery2): print('Error main thread mystery object was GCed') if __name__ == '__main__': test_object_maker_main()But when I run the code I see ...
Output:Creating mystery object in thread MainThread_140259104548672
Creating mystery object in thread Thread-1_140259096856320
Creating mystery object in thread Thread-1_140259096856320
Thread-1_140259096856320 Thread mystery object was GCed
MysteryObject => Thread-1_140259096856320 destroyed
Creating mystery object in thread Thread-1_140259096856320
Thread-1_140259096856320 Thread mystery object was GCed
MysteryObject => Thread-1_140259096856320 destroyed
Creating mystery object in thread Thread-1_140259096856320
Thread-1_140259096856320 Thread mystery object was GCed
MysteryObject => Thread-1_140259096856320 destroyed
MysteryObject => Thread-1_140259096856320 destroyed
Creating mystery object in thread MainThread_140259104548672
Error main thread mystery object was GCed
MysteryObject => MainThread_140259104548672 destroyed
MysteryObject => MainThread_140259104548672 destroyed
I expect objects in thread locals to stick around until the thread ends. What am I missing? I also created a stackoverflow post but haven't got any answers yet.