Reputation: 5444
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
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