<div class="gmail_quote"><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;"><div class="gmail_quote"><div class="im"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div class="gmail_quote"><div>Only really glanced at this, but you seem to be checking only the last thread *after* the loop?  Surely you should be storing all the threads in a list (or someplace) as you create them, and then check them all for liveness and if so join them each in turn, to ensure you only print &#39;FINISHED&#39; once you&#39;ve checked and confirmed that all the threads created have in fact finished.<br>


<br>Walter<br></div></div><br></blockquote><div><br></div></div><div>That makes absolute sense. Doh on my part!<br><br>Thanks! </div></div><br>
</blockquote></div><br><div>Just done a little more reading and came across this in an O&#39;Reilly article here <a href="http://www.oreillynet.com/onlamp/blog/2008/01/pymotw_threading.html">http://www.oreillynet.com/onlamp/blog/2008/01/pymotw_threading.html</a></div>
<div><br></div><div>Seems like an elegant way to accomplish a wait until all running threads have finished.</div><div><br></div><div><p style="margin-bottom: 0px; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; ">
<span style="font-weight: bold; ">Using enumerate() to wait for all running threads:</span></p><p style="margin-bottom: 0px; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; ">It is not necessary to retain an explicit handle to all of the daemon threads you start in order to ensure they have completed before exiting the main process. <code style="color: rgb(0, 51, 102); font-family: &#39;Andale Mono&#39;, &#39;Courier New&#39;, Courier, monospace; ">threading.enumerate()</code>returns a list of active <code style="color: rgb(0, 51, 102); font-family: &#39;Andale Mono&#39;, &#39;Courier New&#39;, Courier, monospace; ">Thread</code> instances. The list includes the current thread, and since joining the current thread is not allowed (it introduces a deadlock situation), we must check before joining.</p>
<p style="margin-bottom: 0px; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; "><br></p><p style="margin-bottom: 0px; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; "></p><pre style="clear: both; overflow-x: auto; overflow-y: auto; background-color: rgb(239, 239, 239); font-size: 12px; padding-top: 2px; padding-right: 2px; padding-left: 2px; padding-bottom: 1.5em; width: 586px; ">
<span class="k">import</span> <span class="nn">random</span>
<span class="k">import</span> <span class="nn">threading</span>
<span class="k">import</span> <span class="nn">time</span>

<span class="k">def</span> <span class="nf">worker</span><span class="p">():</span>
    <span class="sd">&quot;&quot;&quot;thread worker function&quot;&quot;&quot;</span>
    <span class="n">t</span> <span class="o">=</span> <span class="n">threading</span><span class="o">.</span><span class="n">currentThread</span><span class="p">()</span>
    <span class="n">pause</span> <span class="o">=</span> <span class="n">random</span><span class="o">.</span><span class="n">randint</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span><span class="mi">5</span><span class="p">)</span>
    <span class="k">print</span> <span class="s">&#39;Starting:&#39;</span><span class="p">,</span> <span class="n">t</span><span class="o">.</span><span class="n">getName</span><span class="p">(),</span> <span class="s">&#39;sleeping&#39;</span><span class="p">,</span> <span class="n">pause</span>
    <span class="n">time</span><span class="o">.</span><span class="n">sleep</span><span class="p">(</span><span class="n">pause</span><span class="p">)</span>
    <span class="k">print</span> <span class="s">&#39;Ending  :&#39;</span><span class="p">,</span> <span class="n">t</span><span class="o">.</span><span class="n">getName</span><span class="p">()</span>
    <span class="k">return</span>

<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">3</span><span class="p">):</span>
    <span class="n">t</span> <span class="o">=</span> <span class="n">threading</span><span class="o">.</span><span class="n">Thread</span><span class="p">(</span><span class="n">target</span><span class="o">=</span><span class="n">worker</span><span class="p">)</span>
    <span class="n">t</span><span class="o">.</span><span class="n">setDaemon</span><span class="p">(</span><span class="bp">True</span><span class="p">)</span>
    <span class="n">t</span><span class="o">.</span><span class="n">start</span><span class="p">()</span>

<span class="n">main_thread</span> <span class="o">=</span> <span class="n">threading</span><span class="o">.</span><span class="n">currentThread</span><span class="p">()</span>
<span class="k">for</span> <span class="n">t</span> <span class="ow">in</span> <span class="n">threading</span><span class="o">.</span><span class="n">enumerate</span><span class="p">():</span>
    <span class="k">if</span> <span class="n">t</span> <span class="ow">is</span> <span class="n">main_thread</span><span class="p">:</span>
        <span class="k">continue</span>
    <span class="k">print</span> <span class="s">&#39;Joining :&#39;</span><span class="p">,</span> <span class="n">t</span><span class="o">.</span><span class="n">getName</span><span class="p">()</span>
    <span class="n">t</span><span class="o">.</span><span class="n">join</span><span class="p">()</span></pre><p></p></div>