What is import lock in python?
I am reading "The Little Book of Semaphores", and in it he has some code to make python use similar syntax to what he uses in the book. However, when I try to import his code it gives me the following error.
from threading_cleanup import *
RuntimeError: not holding the import lock
I know it has something to do with the watcher function code because if I comment it out the error goes away, the code there makes it so I can use a KeyboardInterrupt to end the program.
Is there any way to fix the error?
threading_cleanup.py
import threading
import time
import os
import signal
import sys
__all__ = ['Thread', 'Semaphore', 'watcher']
class Thread(threading.Thread):
def __init__(self, target, *args):
threading.Thread.__init__(self, target=target, args=args)
self.start()
class Semaphore(threading._Semaphore):
wait = threading._Semaphore.acquire
def signal(self, n=1):
for _ in range(n): self.release()
def value(self):
开发者_运维问答 return self._Semaphore__value
def watcher():
child = os.fork()
if child == 0: return
try:
os.wait()
except KeyboardInterrupt:
print 'KeyboardInterrupt'
os.kill(child, signal.SIGKILL)
sys.exit()
watcher()
The title of this question asks what the import lock is.
The import lock is the part of Python's import
implementation that makes programs fail if you violate these obscure restrictions:
https://docs.python.org/2/library/threading.html#importing-in-threaded-code
In your case, because you call watcher()
directly in your module, it can't start threads unless that module happens to be the main module. Here's an example:
python2.7 - import silently locks up the thread
Your example seems a bit different though, as it involves processes. If I reduce your threading_cleanup.py
to:
import os
def watcher():
child = os.fork()
watcher()
I still get the same error:
File "main.py", line 1, in <module>
import threading_cleanup.py
RuntimeError: not holding the import lock
So gosh that's not an import lock. Except the error message says it's an import lock, now doesn't it? Sounds like a bug in the error message text.
On my setup the error only happens in interpreted mode.
It seems that the interpreter doesn't like that the module does a fork while it is still importing it.
The error goes away if you remove the watcher()
call or if you wrap it in an if __name__ == '__main__':
.
In general, code executed by a Python module should be only for initialization of globals and singletons.
Oh! After the import, you can call threading_cleanup.watcher()
from the interpreter, and it doesn't raise the exception.
Eh! I realized I didn't answer the title of your question:
The call to fork()
creates a new process of the interpreter; one that will have to import the module to start executing. In interpreted mode, you are making that happen while the module is still being imported, and thus locked. In interpreted mode, the interactive interpreter is the main program. In execution mode, as in python mymodule.py
, the module is the main program, so it doesn't get imported. Does that make sense?
精彩评论