Unexpected behavior when using python thread locks and circulair imports
Question: I wrote a simple test program using thread locks. This program does not behave
as expected, and the python interpreter does not complain.

test1.py:

    
    
    from __future__ import with_statement
    from threading import Thread, RLock
    import time
    import test2
    
    lock = RLock()
    
    class Test1(object):
        def __init__(self):
            print("Start Test1")
            self.test2 = test2.Test2()
            self.__Thread = Thread(target=self.myThread, name="thread")
            self.__Thread.daemon = True
            self.__Thread.start()
            self.test1Method()
    
        def test1Method(self):
            print("start test1Method")
            with lock:
                print("entered test1Method")
                time.sleep(5)
                print("end test1Method")
    
        def myThread(self):
            self.test2.test2Method()
    
    if __name__ == "__main__":
        client = Test1()
        raw_input()
    

test2.py:

    
    
    from __future__ import with_statement
    import time
    import test1
    
    lock = test1.lock
    
    class Test2(object):
        def __init__(self):
            print("Start Test2")
    
        def test2Method(self):
            print("start test2Method")
            with lock:
                print("entered test2Method")
                time.sleep(5)
                print("end test2Method")
    

Both sleeps are executed at the same time! Not what I expected when using the
lock.

When test2Method is moved to test1.py everything works fine. When I create the
lock in test2.py and import it in test1.py everything works fine. When I
create the lock in a separate source file and import it both in test1.py and
test2.py everything works fine.

Probably it has to do with circulair imports.

But why doesn't python complain about this?


Answer: In Python when you execute a python script using `$ python test1.py` what
happen is that your `test1.py` will be imported as `__main__` instead of
`test1`, so if you want to get the lock defined in the launched script you
shouldn't `import test1` but you should `import __main__` because if you do
the first one you will create another lock that is different from the
`__main__.lock` (`test1.lock != __main__.lock`).

So one fix to your problem (**which far from being the best**) and to **see
what is happening** you can change your 2 script to this:

test1.py:

    
    
    from __future__ import with_statement
    from threading import Thread, RLock
    import time
    
    lock = RLock()
    
    class Test1(object):
        def __init__(self):
            print("Start Test1")
            import test2    # <<<<<<<<<<<<<<<<<<<<<<<< Import is done here to be able to refer to __main__.lock.
            self.test2 = test2.Test2()
            self.__Thread = Thread(target=self.myThread, name="thread")
            self.__Thread.daemon = True
            self.__Thread.start()
            self.test1Method()
    
        def test1Method(self):
            print("start test1Method")
            with lock:
                print("entered test1Method")
                time.sleep(5)
                print("end test1Method")
    
        def myThread(self):
            self.test2.test2Method()
    
    if __name__ == "__main__":
        client = Test1()
        raw_input()
    

test2.py:

    
    
    from __future__ import with_statement
    import time
    # <<<<<<<<<<<<<<<<<<<<<<<<<<<<< test1 is changed to __main__ to get the same lock as the one used in the launched script.
    import __main__
    
    lock = __main__.lock
    
    class Test2(object):
        def __init__(self):
            print("Start Test2")
    
        def test2Method(self):
            print("start test2Method")
            with lock:
                print("entered test2Method")
                time.sleep(5)
                print("end test2Method")
    

HTH,

