Search code examples
pythonpython-3.xpython-multithreading

__init__ is not called


in the below code I am learning the difference between new and init. when I run the code I receive the following error:

error:

cls: <class '__main__.ThreadsWithSync'>
Traceback (most recent call last):
File "m:\python lessons\ThreadsWithSync.py", line 37, in <module>
    ThreadsWithSync()
File "m:\python lessons\ThreadsWithSync.py", line 12, in __new__
    cls.onCreateObject()
File "m:\python lessons\ThreadsWithSync.py", line 20, in onCreateObject
    print(instance)
File "C:\Users\Amr.Bakri\AppData\Local\Programs\Python\Python39\lib\threading.py", line 842, in __repr__
assert self._initialized, "Thread.__init__() was not called"
AssertionError: Thread.__init__() was not called

code:

import threading
import logging
import time

class ThreadsWithSync(threading.Thread):

def __new__(cls):
    """
    For object creation
    """
    print("cls: %s"%(cls))
    cls.onCreateObject()
    
@classmethod
def onCreateObject(cls):
    """
    This will be invoked once the creation procedure of the object begins.
    """
    instance = super(ThreadsWithSync, cls).__new__(cls)
    print(instance)
    return instance

def __init__(self):
    """
    For object initialization
    """
    threading.Thread.__init__(self)
    print("self: %s"%(self))
    self.onInitializeObject()

def onInitializeObject(self):
    """
    This will be invoked once the initialization procedure of the object begins.
    """
    print("self: %s"%(self))
    
ThreadsWithSync()

Solution

  • The __repr__ in threding.Thread checks whether the object has been initialized or not. This is being called when you are doing print(instance) inside onCreateObject. That check is required by the __repr__ implementation to function correctly (without throwing an AttributeError).

    If you overwrite the __repr__ from threading.Thread then your example will work

    class ThreadWithSync(threading.Thread):
        ...
        def __repr__(self):
            return "hey"
    

    This results in the output:

    cls: <class '__main__.ThreadsWithSync'>
    hey
    

    Edited to add full example:

    import threading
    
    
    class ThreadsWithSync(threading.Thread):
        def __new__(cls):
            """
            For object creation
            """
            print("cls: %s" % (cls))
            cls.onCreateObject()
    
        @classmethod
        def onCreateObject(cls):
            """
            This will be invoked once the creation procedure of the object begins.
            """
            instance = super(ThreadsWithSync, cls).__new__(cls)
            print(instance)
            return instance
    
        def __init__(self):
            """
            For object initialization
            """
            super(ThreadsWithSync, self).__init__(self)
            print("self: %s" % (self))
            self.onInitializeObject()
    
        def onInitializeObject(self):
            """
            This will be invoked once the initialization procedure of the object begins.
            """
            print("self: %s" % (self))
    
        def __repr__(self):
            return id(self)
    
    
    ThreadsWithSync()