The thing is that I'm looking at the confusion of the following piece of code, obviously while True, why is the code not dead loop??
Class D (threading. Thread): def __init__ (self, queue): Threading. Thread.__init__ (self) self.queue = Queue def run (self): while True: url = self.queue.get () Self.download_file (URL) self.queue.task_done () def download_file (self, URL): h = urllib2.urlopen (URL) f = os.path.basename (URL) + '. html ' with open (F, ' WB ') as F: while True: c = h.read (1024) if not C: break F.write (c) if __name__ = = "__main__": urls= [' http://www.baidu.com ', '/HTTP/ Www.sina.com '] queue = Queue.queue () for I in range (5): t = D (queue) T.setdaemon (True) T.start () for u in URLs: queue.put (U) queue.join ()
It's been a simple thought before Setdaemon is set as a background thread, no further digging inside the meaning.
The key to the problem is Setdaemon, in the bottom of the thread module, as long as the main thread ends, all other threads will end, it is obvious that the main thread end Python will destroy the runtime environment, the main thread will certainly be ended. So the thread Setdaemon of the threading module is
To solve this problem, if Setdaemon (True), then, as before, the main thread ends and all the child threads will end.
If Setdaemon (False), the main thread will wait for the threads to end, equivalent to the Join method that you call the thread.
So if the above Setdaemon is commented and modified to True, then the program will die loop.
In fact, we do not recommend the above practice, the above practice a bit the flavor of the thread pool, but if you have seen some of the python thread pooling implementation, while True
There must be a detection exit statement in the loop because it is more pythonic in the Python world than in obscurity. But unfortunately, the code above comes
Self-<< write high-quality code: 91 Suggestions for improving Python programs >> I didn't spray this book, but I think the code example is really debatable.
You may wonder how Setdaemon (False) is equivalent to a thread join? , no hurry, and listen to my slow way.
This problem is not resolved, the threading module introduces the _mainthread object
# Special thread class to represent the main thread# this was garbage collected through an exit Handlerclass _mainthread (Th Read): Def __init__ (self): thread.__init__ (Self, name= "Mainthread") self._thread__started.set () se Lf._set_ident () with _active_limbo_lock: _active[_get_ident ()] = self def _set_daemon (self): R Eturn False def _exitfunc (self): self._thread__stop () t = _picksomenondaemonthread () If T: If __debug__: Self._note ("%s:waiting for other Threads", self) while T:t.join () t = _picksomenondaemonthread () If __debug__: Self._note ("%s:exiting", self) self._thread __delete () def _picksomenondaemonthread (): For T in enumerate (): If not T.daemon and T.is_alive (): RET Urn T return none# Create the main thread object,# and make it available for the interpreter# (Py_main) as threading._s Hutdown._shutdown = _maiNthread (). _exitfunc
In fact, _mainthread didn't do anything, the only contribution was to create an instance when the threading module was imported and _exitfunc
Assign a value to the _shutdown function. _exitfunc collects all non-daemon and alive threads and invokes the thread's join method. Oh, it turns out.
_mainthread quietly in the behind-the-scenes struggle, the remaining problem is who calls the _shutdown function?
When Python is going to destroy the runtime before it is sure to call, so open pythonrun.c, you will find the following function
/* Wait until Threading._shutdown completes, provided the threading module is imported in the first place . The shutdown routine would wait until all Non-daemon "threading" Threads has completed. */static voidwait_for_thread_s Hutdown (void) {#ifdef with_thread pyobject *result; Pythreadstate *tstate = Pythreadstate_get (); Pyobject *threading = pymapping_getitemstring (Tstate->interp->modules, "threading"); if (threading = = NULL) {/ * Threading Not imported * /Pyerr_clear (); return; } result = Pyobject_callmethod (threading, "_shutdown", ""); if (result = = NULL) pyerr_writeunraisable (threading); else py_decref (result); Py_decref (threading); #endif}
The original is this guy in the mischief, rose Insight, the original in C there are calls to the PY code requirements AH. No way, who let threading module is pure PY
Code It!!!
The beauty of Python [from rookie to master]--threading Daemon Threading Principle interpretation