qichao_he
qichao_he

Reputation: 5444

The lock instance cannot be shared between two .py files

Recently I have been touching the multithreading area with python. The following example will better illustrate my question: So I have two .py files, one is test.py and another is test2.py

in test.py:

import time
from datetime import datetime
from threading import Thread, Lock

lock = Lock()

import logging
logging.basicConfig(level=logging.INFO, format='%(asctime)s %(threadName)s %(name)s.%(funcName)s [%(levelname)s]: %(message)s')

def foo1():
    while True:
        with lock:
            logging.info(datetime.now())
            time.sleep(0.2)

if __name__ == '__main__':
    from test2 import foo2
    Thread(target=foo1).start()
    Thread(target=foo2).start()

in test2.py:

import time
from datetime import datetime
from test import logging, lock

def foo2():
    while True:
        with lock:
            logging.info( datetime.now() )
            time.sleep(5)

output:

2017-03-17 17:11:06,210 Thread-1 root.foo1 [INFO]: 2017-03-17 17:11:06.210000
2017-03-17 17:11:06,210 Thread-2 root.foo2 [INFO]: 2017-03-17 17:11:06.210000
2017-03-17 17:11:06,415 Thread-1 root.foo1 [INFO]: 2017-03-17 17:11:06.416000
2017-03-17 17:11:06,619 Thread-1 root.foo1 [INFO]: 2017-03-17 17:11:06.620000

So, the lock seems to have no effect. I tested if I put foo1 and foo2 in the same .py file, it will work.

Could anyone tell me why?

And I know this might involve some elementary knowledge that how python handles import, please forgive me for my ignorance.

Upvotes: 2

Views: 667

Answers (1)

user2357112
user2357112

Reputation: 281476

This is one of the really confusing parts of Python's import system. You don't have two modules, test and test2. You have three modules, __main__, test, and test2. Similarly, you don't have one lock, test.lock. You have two locks, __main__.lock and test.lock.

When you run python test.py, Python starts executing test.py as the __main__ module, not the test module. When __main__ imports test2 and test2 imports test, Python starts running test.py again, this time as the test module. Everything not inside if __name__ == '__main__' gets run again, including lock = Lock(), making a second lock.

In __main__, the two functions you set your threads to run are __main__.foo1 and test2.foo2. __main__.foo1 is using __main__.lock, while test2.foo2 is using the test.lock it imported from test. Since these are different locks, there is no mutual exclusion.


Not directly related to your problem, but don't call your modules test, because there's already a standard library module by that name, and don't use circular imports. Having test import test2 and test2 import test will lead to all sorts of nasty bugs.

Upvotes: 5

Related Questions