﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-&lt;h1&gt;&lt;font color="red" size="36"&gt;︻┳═一Java&lt;/font&gt;&lt;/h1&gt;-文章分类-Python</title><link>http://www.blogjava.net/rain1102/category/25779.html</link><description>&lt;b&gt;&lt;font color="#3C1435"&gt;最低奋斗目标：&lt;/font&gt;&lt;font color="red"&gt;农妇，山泉，有点田！&lt;/font&gt;&lt;/b&gt;</description><language>zh-cn</language><lastBuildDate>Wed, 17 Oct 2007 14:35:54 GMT</lastBuildDate><pubDate>Wed, 17 Oct 2007 14:35:54 GMT</pubDate><ttl>60</ttl><item><title>dictionary 的字符串格式化</title><link>http://www.blogjava.net/rain1102/articles/153521.html</link><dc:creator>Eric.Chau</dc:creator><author>Eric.Chau</author><pubDate>Wed, 17 Oct 2007 03:56:00 GMT</pubDate><guid>http://www.blogjava.net/rain1102/articles/153521.html</guid><wfw:comment>http://www.blogjava.net/rain1102/comments/153521.html</wfw:comment><comments>http://www.blogjava.net/rain1102/articles/153521.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/rain1102/comments/commentRss/153521.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/rain1102/services/trackbacks/153521.html</trackback:ping><description><![CDATA[<tt class="prompt">&gt;&gt;&gt; </tt><span class="userinput">params = {<span class="pystring">"server"</span>:<span class="pystring">"mpilgrim"</span>, <span class="pystring">"database"</span>:<span class="pystring">"master"</span>, <span class="pystring">"uid"</span>:<span class="pystring">"sa"</span>, <span class="pystring">"pwd"</span>:<span class="pystring">"secret"</span>}</span><br />
<tt class="prompt">&gt;&gt;&gt; </tt><span class="userinput"><span class="pystring">"%(pwd)s"</span> % params</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
<span class="computeroutput">'secret'</span><br />
<tt class="prompt">&gt;&gt;&gt; </tt><span class="userinput"><span class="pystring">"%(pwd)s is not a good password for %(uid)s"</span> % params</span> <br />
<span class="computeroutput">'secret is not a good password for sa'</span><br />
<tt class="prompt">&gt;&gt;&gt; </tt><span class="userinput"><span class="pystring">"%(database)s of mind, %(database)s of body"</span> % params</span> <br />
<span class="computeroutput">'master of mind, master of body'</span><br />
1.这种字符串格式化形式不用显示的值的 tuple，而是使用一个 dictionary，<tt class="varname">params</tt>。并且标记也不是在字符串中的一个简单 <tt class="literal">%s</tt>，而是包含了一个用括号包围起来的名字。这个名字是 <tt class="varname">params</tt> dictionary 中的一个键字，并且将 <tt class="literal">%(pwd)s</tt> 标记所在的地方替换成相应的值 <tt class="literal">secret</tt>。<br />
2.基于 dictionary 的字符串格式化可用于任意数量的有名的键字。每个键字必须在一个给定的 dictionary 中存在，否则这个格式化操作将失败并引发一个 <tt class="errorcode">KeyError</tt> 的异常。<br />
3.您甚至可以两次指定同一键字，每个键字发生之处将被同一个值所替换。<img src ="http://www.blogjava.net/rain1102/aggbug/153521.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/rain1102/" target="_blank">Eric.Chau</a> 2007-10-17 11:56 <a href="http://www.blogjava.net/rain1102/articles/153521.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>使用SGMLParser和urllib解析HTML文件</title><link>http://www.blogjava.net/rain1102/articles/153500.html</link><dc:creator>Eric.Chau</dc:creator><author>Eric.Chau</author><pubDate>Wed, 17 Oct 2007 02:51:00 GMT</pubDate><guid>http://www.blogjava.net/rain1102/articles/153500.html</guid><wfw:comment>http://www.blogjava.net/rain1102/comments/153500.html</wfw:comment><comments>http://www.blogjava.net/rain1102/articles/153500.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/rain1102/comments/commentRss/153500.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/rain1102/services/trackbacks/153500.html</trackback:ping><description><![CDATA[<tt class="filename">sgmllib.py</tt> 包含一个重要的类: <tt class="classname">SGMLParser</tt>。<tt class="classname">SGMLParser</tt> 将 <span class="acronym">HTML</span> 分解成有用的片段，比如开始标记和结束标记。一旦它成功地分解出某个数据为一个有用的片段，它会根据所发现的数据，调用一个自身内部的方法。为了使用这个分析器，您需要子类化 <tt class="classname">SGMLParser</tt> 类，并且覆盖这些方法。<br />
<tt class="classname">SGMLParser</tt> 将 <span class="acronym">HTML</span> 分析成 8 类数据，然后对每一类调用单独的方法:<br />
<dt><span class="term">开始标记 (Start tag)</span>
<dd>是一个开始一个块的 <span class="acronym">HTML</span> 标记，象 <tt class="sgmltag-element">&lt;html&gt;</tt>，<tt class="sgmltag-element">&lt;head&gt;</tt>，<tt class="sgmltag-element">&lt;body&gt;</tt> 或 <tt class="sgmltag-element">&lt;pre&gt;</tt> 等，或是一个独一的标记，象 <tt class="sgmltag-element">&lt;br&gt;</tt> 或 <tt class="sgmltag-element">&lt;img&gt;</tt> 等。当它找到一个开始标记 <em class="replaceable"><tt>tagname</tt></em>，<tt class="classname">SGMLParser</tt> 将查找名为 <tt class="function">start_<em class="replaceable"><tt>tagname</tt></em></tt> 或 <tt class="function">do_<em class="replaceable"><tt>tagname</tt></em></tt> 的方法。例如，当它找到一个 <tt class="sgmltag-element">&lt;pre&gt;</tt> 标记，它将查找一个 <tt class="function">start_pre</tt> 或 <tt class="function">do_pre</tt> 的方法。如果找到了，<tt class="classname">SGMLParser</tt> 会使用这个标记的属性列表来调用这个方法；否则，它用这个标记的名字和属性列表来调用 <tt class="function">unknown_starttag</tt> 方法。
<dt><span class="term">结束标记 (End tag)</span>
<dd>是结束一个块的 <span class="acronym">HTML</span> 标记，象 <tt class="sgmltag-element">&lt;/html&gt;</tt>，<tt class="sgmltag-element">&lt;/head&gt;</tt>，<tt class="sgmltag-element">&lt;/body&gt;</tt> 或 <tt class="sgmltag-element">&lt;/pre&gt;</tt> 等。当找到一个结束标记时，<tt class="classname">SGMLParser</tt> 将查找名为 <tt class="function">end_<em class="replaceable"><tt>tagname</tt></em></tt> 的方法。如果找到，<tt class="classname">SGMLParser</tt> 调用这个方法，否则它使用标记的名字来调用 <tt class="function">unknown_endtag</tt> 。
<dt><span class="term">字符引用 (Character reference)</span>
<dd>用字符的十进制或等同的十六进制来表示的转义字符，象 <tt class="literal">&#160;</tt>。当找到，<tt class="classname">SGMLParser</tt> 使用十进制或等同的十六进制字符文本来调用 <tt class="function">handle_charref</tt> 。
<dt><span class="term">实体引用 (Entity reference)</span>
<dd><span class="acronym">HTML</span> 实体，象 <tt class="literal">&amp;copy;</tt>。当找到，<tt class="classname">SGMLParser</tt> 使用 <span class="acronym">HTML</span> 实体的名字来调用 <tt class="function">handle_entityref</tt> 。
<dt><span class="term">注释 (Comment)</span>
<dd><span class="acronym">HTML</span> 注释, 包括在 <tt class="literal">&lt;!-- ... --&gt;</tt>之间。当找到，<tt class="classname">SGMLParser</tt> 用注释内容来调用 <tt class="function">handle_comment</tt>。
<dt><span class="term">处理指令 (Processing instruction)</span>
<dd><span class="acronym">HTML</span> 处理指令，包括在 <tt class="literal">&lt;? ... &gt;</tt> 之间。当找到，<tt class="classname">SGMLParser</tt> 用处理指令内容来调用 <tt class="function">handle_pi</tt>。
<dt><span class="term">声明 (Declaration)</span>
<dd><span class="acronym">HTML</span> 声明，如 <tt class="sgmltag-element">DOCTYPE</tt>，包括在 <tt class="literal">&lt;! ... &gt;</tt>之间。当找到，<tt class="classname">SGMLParser</tt> 用声明内容来调用 <tt class="function">handle_decl</tt>。
<dt><span class="term">文本数据 (Text data)</span>
<dd>文本块。不满足其它 7 种类别的任何东西。当找到，<tt class="classname">SGMLParser</tt> 用文本来调用 <tt class="function">handle_data</tt>。</dd>
<p><tt class="filename">urllib</tt> 模块是标准 <span class="application">Python</span> 库的一部分。它包含了一些函数，可以从基于互联网的 <span class="acronym">URL</span> (主要指网页) 来获取信息并且真正取回数据。<tt class="filename">urllib</tt> 模块最简单的使用是提取用 <tt class="function">urlopen</tt> 函数取回的网页的整个文本。打开一个 <span class="acronym">URL</span> 同 <a title="6.2.&nbsp;与文件对象共事" href="mk:@MSITStore:C:\Documents%20and%20Settings\maggie\桌面\Dive.Into.Python-zh-cn-5.4-with-code.chm::/file_handling/file_objects.html">打开一个文件</a>相似。<tt class="function">urlopen</tt> 的返回值是象文件一样的对象，它具有一个文件对象一样的方法。使用由 <tt class="function">urlopen</tt> 所返回的类文件对象所能做的最简单的事情就是 <tt class="function">read</tt>，它可以将网页的整个 <span class="acronym">HTML</span> 读到一个字符串中。这个对象也支持 <tt class="function">readlines</tt> 方法，这个方法可以将文本按行放入一个列表中。当用完这个对象，要确保将它 <tt class="function">close</tt>，就如同一个普通的文件对象。</p>
&nbsp;<tt class="filename">urllister.py</tt> <br />
<p>from sgmllib import SGMLParser</p>
<p>class URLLister(SGMLParser):<br />
&nbsp;&nbsp;&nbsp; def reset(self):<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SGMLParser.reset(self)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.urls=[]<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.imgs=[]<br />
&nbsp;&nbsp;&nbsp; def start_a(self, attrs):<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; href = [v for k, v in attrs if k=='href']<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if href:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.urls.extend(href)<br />
&nbsp;&nbsp;&nbsp; def start_img(self, attrs):<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; img = [v for k, v in attrs if k=='src']<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if img:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.imgs.extend(img)<br />
</p>
<tt class="function">1.reset</tt> 由 <tt class="classname">SGMLParser</tt> 的 <tt class="function">__init__</tt> 方法来调用，也可以在创建一个分析器实例时手工来调用。所以如果您需要做初始化，在 <tt class="function">reset</tt> 中去做，而不要在 <tt class="function">__init__</tt> 中做。这样当某人重用一个分析器实例时，会正确地重新初始化。<br />
2.象 <tt class="literal">k=='href'</tt> 的字符串比较是区分大小写的，但是这里是安全的。因为 <tt class="classname">SGMLParser</tt> 会在创建 <tt class="varname">attrs</tt> 时将属性名转化为小写。<br />
test.py<br />
import urllib, urllister<br />
usock=urllib.urlopen("http://www.blogjava.net/rain1102")<br />
parser=urllister.URLLister()<br />
parser.feed(usock.read())<br />
usock.close()<br />
parser.close()<br />
for url in parser.urls:print url<br />
for img in parser.imgs:print img<img src ="http://www.blogjava.net/rain1102/aggbug/153500.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/rain1102/" target="_blank">Eric.Chau</a> 2007-10-17 10:51 <a href="http://www.blogjava.net/rain1102/articles/153500.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>安装Django</title><link>http://www.blogjava.net/rain1102/articles/148419.html</link><dc:creator>Eric.Chau</dc:creator><author>Eric.Chau</author><pubDate>Wed, 26 Sep 2007 11:15:00 GMT</pubDate><guid>http://www.blogjava.net/rain1102/articles/148419.html</guid><wfw:comment>http://www.blogjava.net/rain1102/comments/148419.html</wfw:comment><comments>http://www.blogjava.net/rain1102/articles/148419.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/rain1102/comments/commentRss/148419.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/rain1102/services/trackbacks/148419.html</trackback:ping><description><![CDATA[<p>安装django<br />
1.下载django，使用SVN：http://code.djangoproject.com/svn/django/trunk<br />
2.使用dos进入之前下载的目录，使用命令：setup.py install</p>
<p><br />
Install Apache 2.x : http://httpd.apache.org/<br />
Install mod_python : http://www.modpython.org/</p>
<p><br />
安装PIL:http://www.pythonware.com/products/pil/</p>
<p><br />
PIL是Python Imaging Library缩写，主要用来处理图片用的，这里安装它是为了在Django系统中用它来对上传的图片自动的生成缩略图的。安装方法也相当的简单，直接双击运行PIL-1.1.5.win32-py2.4.exe这个文件，然后一路next即可。因为之前已经安装好了python，所以PIL的安装程序会从注册表中读取到python安装的路经，然后就自动地把PIL安装到python\lib\site-packages\PIL下面了</p>
<p><br />
创建项目：django-admin.py startproject myproject<br />
&nbsp;&nbsp; cd myproject<br />
&nbsp;&nbsp; python manage.py runserver</p>
<p><br />
创建app：manage.py startapp wiki</p>
<p>初始化数据库，使用 django-admin.py 或 manage.py 都可以: manage.py syncdb</p><img src ="http://www.blogjava.net/rain1102/aggbug/148419.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/rain1102/" target="_blank">Eric.Chau</a> 2007-09-26 19:15 <a href="http://www.blogjava.net/rain1102/articles/148419.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Pylons相关软件安装</title><link>http://www.blogjava.net/rain1102/articles/148418.html</link><dc:creator>Eric.Chau</dc:creator><author>Eric.Chau</author><pubDate>Wed, 26 Sep 2007 11:06:00 GMT</pubDate><guid>http://www.blogjava.net/rain1102/articles/148418.html</guid><wfw:comment>http://www.blogjava.net/rain1102/comments/148418.html</wfw:comment><comments>http://www.blogjava.net/rain1102/articles/148418.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/rain1102/comments/commentRss/148418.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/rain1102/services/trackbacks/148418.html</trackback:ping><description><![CDATA[1.&nbsp;安装 python<br />
&nbsp;&nbsp;&nbsp;&nbsp;D:\Python25<br />
2. 设置环境变量<br />
&nbsp;&nbsp;&nbsp;&nbsp;Path中添加;D:\Python25;D:\Python25\Scripts<br />
3. 安装ez_setup<br />
&nbsp;&nbsp;&nbsp;&nbsp;<a href="http://peak.telecommunity.com/dist/ez_setup.py"><font color="#000000">下载ez_setup.py:</font>http://peak.telecommunity.com/dist/ez_setup.py</a><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;存储在D:\ez_setup.py<br />
4. 安装Pylons<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;D:\&gt;easy_install pylons<br />
5. 创建工程<br />
&nbsp;&nbsp;&nbsp;&nbsp;D:\workspace&gt;paster create --template=pylons helloworld<br />
6. 启动服务<br />
&nbsp;&nbsp;&nbsp;&nbsp;D:\workspace&gt;cd helloworld (explorer helloword)<br />
&nbsp;&nbsp;&nbsp;&nbsp;D:\workspace\helloworld&gt;paster serve --reload development.ini<img src ="http://www.blogjava.net/rain1102/aggbug/148418.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/rain1102/" target="_blank">Eric.Chau</a> 2007-09-26 19:06 <a href="http://www.blogjava.net/rain1102/articles/148418.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Python线程编程（二）简单的线程同步</title><link>http://www.blogjava.net/rain1102/articles/148074.html</link><dc:creator>Eric.Chau</dc:creator><author>Eric.Chau</author><pubDate>Tue, 25 Sep 2007 08:02:00 GMT</pubDate><guid>http://www.blogjava.net/rain1102/articles/148074.html</guid><wfw:comment>http://www.blogjava.net/rain1102/comments/148074.html</wfw:comment><comments>http://www.blogjava.net/rain1102/articles/148074.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/rain1102/comments/commentRss/148074.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/rain1102/services/trackbacks/148074.html</trackback:ping><description><![CDATA[多个执行线程经常要共享数据，如果仅仅读取共享数据还好，但是如果多个线程要修改共享数据的话就可能出现无法预料的结果。
<p>&nbsp;&nbsp;&nbsp; 假如两个线程对象<font color="#ff6600">t1</font>和<font color="#ff6600">t2</font>都要对数值<font color="#ff6600">num=0</font>进行增1运算，那么<font color="#ff6600">t1</font>和<font color="#ff6600">t2</font>都各对<font color="#ff6600">num</font>修改<font color="#ff6600">10</font>次的话，那么<font color="#ff6600">num</font>最终的结果应该为<font color="#ff6600">20</font>。但是如果当<font color="#ff6600">t1</font>取得<font color="#ff6600">num</font>的值时（假如此时<font color="#ff6600">num</font>为<font color="#ff6600">0</font>），系统把<font color="#ff6600">t1</font>调度为&#8220;<font color="#ff6600">sleeping</font>&#8221;状态，而此时<font color="#ff6600">t2</font>转换为&#8220;<font color="#ff6600">running</font>&#8221;状态，此时<font color="#ff6600">t2</font>获得的<font color="#ff6600">num</font>的值也为<font color="#ff6600">0</font>，然后他把<font color="#ff6600">num+1</font>的值<font color="#ff6600">1</font>赋给<font color="#ff6600">num</font>。系统又把<font color="#ff6600">t2</font>转化为&#8220;<font color="#ff6600">sleeping</font>&#8221;状态，<font color="#ff6600">t1</font>为&#8220;<font color="#ff6600">running</font>&#8221;状态，由于<font color="#ff6600">t1</font>已经得到<font color="#ff6600">num</font>值为<font color="#ff6600">0</font>，所以他也把<font color="#ff6600">num+1</font>的值赋给了<font color="#ff6600">num</font>为<font color="#ff6600">1</font>。本来是<font color="#ff6600">2</font>次增<font color="#ff6600">1</font>运行，结果却是<font color="#ff6600">num</font>只增了<font color="#ff6600">1</font>次。类似这样的情况在多线程同时执行的时候是有可能发生的。所以为了防止这类情况的出现就要使用线程同步机制。</p>
<p>&nbsp;&nbsp;&nbsp; 最简单的同步机制就是&#8220;锁&#8221;</p>
<p>&nbsp;&nbsp;&nbsp; 锁对象用<font color="#ff6600">threading.RLock</font>类创建</p>
<p>&nbsp;&nbsp;&nbsp; <font color="#ff6600">mylock = threading.RLock()</font></p>
<p>&nbsp;&nbsp;&nbsp; 如何使用锁来同步线程呢？线程可以使用锁的<font color="#ff6600">acquire()</font> （获得）方法，这样锁就进入&#8220;<font color="#ff6600">locked</font>&#8221;状态。每次只有一个线程可以获得锁。如果当另一个线程试图获得这个锁的时候，就会被系统变为&#8220;<font color="#ff6600">blocked</font>&#8221;状态，直到那个拥有锁的线程调用锁的<font color="#ff6600">release()</font> （释放）方法，这样锁就会进入&#8220;<font color="#ff6600">unlocked</font>&#8221;状态。&#8220;<font color="#ff6600">blocked</font>&#8221;状态的线程就会收到一个通知，并有权利获得锁。如果多个线程处于&#8220;<font color="#ff6600">blocked</font>&#8221;状态，所有线程都会先解除&#8220;<font color="#ff6600">blocked</font>&#8221;状态，然后系统选择一个线程来获得锁，其他的线程继续沉默（&#8220;<font color="#ff6600">blocked</font>&#8221;）。</p>
<p><font color="#ff6600">import threading<br />
mylock = threading.RLock()<br />
class mythread(threading.Thread)<br />
&nbsp;&nbsp;&nbsp; ...<br />
&nbsp;&nbsp;&nbsp; def run(self ...):<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ...&nbsp;&nbsp;&nbsp;&nbsp; <font color="#3366ff">#此处 <font color="#ff00ff">不可以 </font>放置修改共享数据的代码<br />
</font>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mylock.acquire()<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ...&nbsp;&nbsp;&nbsp;&nbsp; <font color="#3366ff">#此处 <font color="#ff00ff">可以 </font>放置修改共享数据的代码<br />
</font>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mylock.release()<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ...&nbsp;&nbsp;&nbsp;&nbsp; </font><font color="#3366ff">#此处 <font color="#ff00ff">不可以 </font>放置修改共享数据的代码</font></p>
<p>&nbsp;&nbsp;&nbsp; 我们把修改共享数据的代码称为&#8220;临界区&#8221;，必须将所有&#8220;临界区&#8221;都封闭在同一锁对象的<font color="#ff6600">acquire()</font>和<font color="#ff6600">release()</font>方法调用之间。</p>
<p>&nbsp;&nbsp;&nbsp; 锁只能提供最基本的同步级别。有时需要更复杂的线程同步，例如只在发生某些事件时才访问一个临界区（例如当某个数值改变时）。这就要使用&#8220;条件变量&#8221;。</p>
<p>&nbsp;&nbsp;&nbsp; 条件变量用<font color="#ff6600">threading.Condition</font>类创建</p>
<p>&nbsp;&nbsp;&nbsp; <font color="#ff6600">mycondition = threading.Condition()</font></p>
<p>&nbsp;&nbsp;&nbsp; 条件变量是如何工作的呢？首先一个线程成功获得一个条件变量后，调用此条件变量的<font color="#ff6600">wait()</font>方法会导致这个线程释放这个锁，并进入&#8220;<font color="#ff6600">blocked</font>&#8221;状态，直到另一个线程调用同一个条件变量的<font color="#ff6600">notify()</font>方法来唤醒那个进入&#8220;<font color="#ff6600">blocked</font>&#8221;状态的线程。如果调用这个条件变量的<font color="#ff6600">notifyAll()</font>方法的话就会唤醒所有的在等待的线程。</p>
<p>&nbsp;&nbsp;&nbsp; 如果程序或者线程永远处于&#8220;<font color="#ff6600">blocked</font>&#8221;状态的话，就会发生死锁。所以如果使用了锁、条件变量等同步机制的话，一定要注意仔细检查，防止死锁情况的发生。对于可能产生异常的临界区要使用异常处理机制中的<font color="#ff6600">finally</font>子句来保证释放锁。等待一个条件变量的线程必须用<font color="#ff6600">notify()</font>方法显式的唤醒，否则就永远沉默。保证每一个<font color="#ff6600">wait()</font>方法调用都有一个相对应的<font color="#ff6600">notify()</font>调用，当然也可以调用<font color="#ff6600">notifyAll()</font>方法以防万一。</p><img src ="http://www.blogjava.net/rain1102/aggbug/148074.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/rain1102/" target="_blank">Eric.Chau</a> 2007-09-25 16:02 <a href="http://www.blogjava.net/rain1102/articles/148074.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Python线程编程（三）同步队列</title><link>http://www.blogjava.net/rain1102/articles/148075.html</link><dc:creator>Eric.Chau</dc:creator><author>Eric.Chau</author><pubDate>Tue, 25 Sep 2007 08:02:00 GMT</pubDate><guid>http://www.blogjava.net/rain1102/articles/148075.html</guid><wfw:comment>http://www.blogjava.net/rain1102/comments/148075.html</wfw:comment><comments>http://www.blogjava.net/rain1102/articles/148075.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/rain1102/comments/commentRss/148075.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/rain1102/services/trackbacks/148075.html</trackback:ping><description><![CDATA[我们经常会采用生产者/消费者关系的两个线程来处理一个共享缓冲区的数据。例如一个生产者线程接受用户数据放入一个共享缓冲区里，等待一个消费者线程对数据取出处理。但是如果缓冲区的太小而生产者和消费者两个异步线程的速度不同时，容易出现一个线程等待另一个情况。为了尽可能的缩短共享资源并以相同速度工作的各线程的等待时间，我们可以使用一个&#8220;队列&#8221;来提供额外的缓冲区。<br />
<br />
&nbsp;&nbsp;&nbsp; 创建一个&#8220;队列&#8221;对象<br />
<br />
<font color="#ff9900">&nbsp;&nbsp;&nbsp; import Queue<br />
&nbsp;&nbsp;&nbsp; myqueue = Queue.Queue(maxsize = 10)<br />
<br />
</font>&nbsp;&nbsp;&nbsp; <font color="#ff9900">Queue.Queue</font>类即是一个队列的同步实现。队列长度可为无限或者有限。可通过<font color="#ff9900">Queue</font>的构造函数的可选参数<font color="#ff9900">maxsize</font>来设定队列长度。如果<font color="#ff9900">maxsize</font>小于<font color="#ff9900">1</font>就表示队列长度无限。<br />
<br />
&nbsp;&nbsp;&nbsp; 将一个值放入队列中<br />
<br />
&nbsp;&nbsp;&nbsp; <font color="#ff9900">myqueue.put(10)<br />
</font><br />
&nbsp;&nbsp;&nbsp; 调用队列对象的<font color="#ff9900">put()</font>方法在队尾插入一个项目。<font color="#ff9900">put()</font>有两个参数，第一个<font color="#ff9900">item</font>为必需的，为插入项目的值；第二个<font color="#ff9900">block</font>为可选参数，默认为<font color="#ff9900">1</font>。如果队列当前为空且<font color="#ff9900">block</font>为<font color="#ff9900">1</font>，<font color="#ff9900">put()</font>方法就使调用线程暂停,直到空出一个数据单元。如果<font color="#ff9900">block</font>为<font color="#ff9900">0</font>，<font color="#ff9900">put</font>方法将引发<font color="#ff9900">Full</font>异常。<br />
<br />
&nbsp;&nbsp;&nbsp; 将一个值从队列中取出<br />
<br />
&nbsp;<font color="#ff9900">&nbsp;&nbsp; myqueue.get()<br />
</font><br />
&nbsp;&nbsp;&nbsp; 调用队列对象的<font color="#ff9900">get()</font>方法从队头删除并返回一个项目。可选参数为<font color="#ff9900">block</font>，默认为<font color="#ff9900">1</font>。如果队列为空且<font color="#ff9900">block</font>为<font color="#ff9900">1</font>，<font color="#ff9900">get()</font>就使调用线程暂停，直至有项目可用。如果<font color="#ff9900">block</font>为0，队列将引发<font color="#ff9900">Empty</font>异常。<br />
<br />
&nbsp;&nbsp;&nbsp; 我们用一个例子来展示如何使用<font color="#ff9900">Queue<br />
<br />
</font><font color="#ff9900"># queue_example.py<br />
from Queue import Queue<br />
import threading<br />
import random<br />
import time</font>
<p><font color="#ff9900"># Producer thread<br />
class Producer(threading.Thread):<br />
&nbsp;&nbsp;&nbsp; def __init__(self, threadname, queue):<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; threading.Thread.__init__(self, name = threadname)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.sharedata = queue<br />
&nbsp;&nbsp;&nbsp; def run(self):<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for i in range(20):<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; print self.getName(),'adding',i,'to queue'<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.sharedata.put(i)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; time.sleep(random.randrange(10)/10.0)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; print self.getName(),'Finished'</font></p>
<p><font color="#ff9900"># Consumer thread<br />
class Consumer(threading.Thread):<br />
&nbsp;&nbsp;&nbsp; def __init__(self, threadname, queue):<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; threading.Thread.__init__(self, name = threadname)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.sharedata = queue<br />
&nbsp;&nbsp;&nbsp; def run(self):<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for i in range(20):<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; print self.getName(),'got a value:',self.sharedata.get()<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; time.sleep(random.randrange(10)/10.0)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; print self.getName(),'Finished'</font></p>
<p><font color="#ff9900"># Main thread<br />
def main():<br />
&nbsp;&nbsp;&nbsp; queue = Queue()<br />
&nbsp;&nbsp;&nbsp; producer = Producer('Producer', queue)<br />
&nbsp;&nbsp;&nbsp; consumer = Consumer('Consumer', queue)</font></p>
<p><font color="#ff9900">&nbsp;&nbsp;&nbsp; print 'Starting threads ...'<br />
&nbsp;&nbsp;&nbsp; producer.start()<br />
&nbsp;&nbsp;&nbsp; consumer.start()</font></p>
<p><font color="#ff9900">&nbsp;&nbsp;&nbsp; producer.join()<br />
&nbsp;&nbsp;&nbsp; consumer.join()</font></p>
<p><font color="#ff9900">&nbsp;&nbsp;&nbsp; print 'All threads have terminated.'</font></p>
<p><font color="#ff9900">if __name__ == '__main__':<br />
&nbsp;&nbsp;&nbsp; main()</font></p>
<p>&nbsp;&nbsp;&nbsp; 示例代码中实现了两个类：生产者类<font color="#ff9900">Producer</font>和消费者类<font color="#ff9900">Consumer</font>。前者在一个随机的时间内放入一个值到队列<font color="#ff9900">queue</font>中然后显示出来，后者在一定随机的时间内从队列<font color="#ff9900">queue</font>中取出一个值并显示出来。</p><img src ="http://www.blogjava.net/rain1102/aggbug/148075.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/rain1102/" target="_blank">Eric.Chau</a> 2007-09-25 16:02 <a href="http://www.blogjava.net/rain1102/articles/148075.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Python线程编程（一）线程对象</title><link>http://www.blogjava.net/rain1102/articles/148073.html</link><dc:creator>Eric.Chau</dc:creator><author>Eric.Chau</author><pubDate>Tue, 25 Sep 2007 08:01:00 GMT</pubDate><guid>http://www.blogjava.net/rain1102/articles/148073.html</guid><wfw:comment>http://www.blogjava.net/rain1102/comments/148073.html</wfw:comment><comments>http://www.blogjava.net/rain1102/articles/148073.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/rain1102/comments/commentRss/148073.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/rain1102/services/trackbacks/148073.html</trackback:ping><description><![CDATA[我们在做软件开发的时候很多要用到多线程技术。例如如果做一个下载软件象flashget就要用到、象在线视频工具realplayer也要用到因为要同时下载media stream还要播放。其实例子是很多的。
<p>&nbsp;&nbsp;&nbsp; 线程相对进程来说是&#8220;轻量级&#8221;的，操作系统用较少的资源创建和管理线程。程序中的线程在相同的内存空间中执行，并共享许多相同的资源。</p>
<p>&nbsp;&nbsp;&nbsp; 在<font color="#99cc00">python</font>中如何创建一个线程对象</p>
<p>&nbsp;&nbsp;&nbsp; 如果你要创建一个线程对象，很简单，只要你的类继承<font color="#99cc00">threading.Thread</font>，然后在<font color="#99cc00">__init__</font>里首先调用<font color="#99cc00">threading.Thread</font>的<font color="#99cc00">__init__</font>方法即可</p>
<p><font color="#99cc00">&nbsp;&nbsp;&nbsp; import threading<br />
&nbsp;&nbsp;&nbsp; class mythread(threading.Thread):<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; def __init__(self, threadname):<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; threading.Thread.__init__(self, name = threadname)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ....</font></p>
<p>&nbsp;&nbsp;&nbsp; 这才仅仅是个空线程，我可不是要他拉空车的，他可得给我干点实在活。很简单，重写类的<font color="#99cc00">run()</font>方法即可，把你要在线程执行时做的事情都放到里面</p>
<p><font color="#99cc00">&nbsp;&nbsp;&nbsp; import threading<br />
&nbsp;&nbsp;&nbsp; import time<br />
&nbsp;&nbsp;&nbsp; class mythread(threading.Thread):<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; def __init__(...):<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ....<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; def run(self):<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for i in range(10):<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; print self.getName, i<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; time.sleep(1)</font></p>
<p>&nbsp;&nbsp;&nbsp; 以上代码我们让这个线程在执行之后每隔1秒输出一次信息到屏幕，10次后结束</p>
<p>&nbsp;&nbsp;&nbsp; <font color="#99cc00">getName()</font>是<font color="#99cc00">threading.Thread</font>类的一个方法，用来获得这个线程对象的<font color="#99cc00">name</font>。还有一个方法<font color="#99cc00">setName()</font>当然就是来设置这个线程对象的<font color="#99cc00">name</font>的了。</p>
<p>&nbsp;&nbsp;&nbsp; 如果要创建一个线程，首先就要先创建一个线程对象</p>
<p><font color="#99cc00">&nbsp;&nbsp;&nbsp; mythread1 = mythread('mythread 1')</font></p>
<p>&nbsp;&nbsp;&nbsp; 一个线程对象被创建后，他就处于&#8220;<font color="#99cc00">born</font>&#8221;（诞生状态）</p>
<p>&nbsp;&nbsp;&nbsp; 如何让这个线程对象开始运行呢?只要调用线程对象的<font color="#99cc00">start()</font>方法即可</p>
<p><font color="#99cc00">&nbsp;&nbsp;&nbsp; mythread1.start()</font></p>
<p>&nbsp;&nbsp;&nbsp; 现在线程就处于&#8220;<font color="#99cc00">ready</font>&#8221;状态或者也称为&#8220;<font color="#99cc00">runnable</font>&#8221;状态。</p>
<p>&nbsp;&nbsp;&nbsp; 奇怪吗？不是已经<font color="#99cc00">start</font>了吗？为什么不称为&#8220;<font color="#99cc00">running</font>&#8221;状态呢？其实是有原因的。因为我们的计算机一般是不具有真正并行处理能力的。我们所谓的多线程只是把时间分成片段，然后隔一个时间段就让一个线程执行一下，然后进入&#8220;<font color="#99cc00">sleeping</font>&nbsp;&#8221;状态，然后唤醒另一个在&#8220;<font color="#99cc00">sleeping</font>&#8221;的线程，如此循环<font color="#99cc00">runnable-&gt;sleeping-&gt;runnable...</font> ，只是因为计算机执行速度很快，而时间片段间隔很小，我们感受不到，以为是同时进行的。所以说一个线程在<font color="#99cc00">start</font>了之后只是处在了可以运行的状态，他什么时候运行还是由系统来进行调度的。</p>
<p>&nbsp;&nbsp;&nbsp; 那一个线程什么时候会&#8220;<font color="#99cc00">dead</font>&#8221;呢？一般来说当线程对象的<font color="#99cc00">run</font>方法执行结束或者在执行中抛出异常的话，那么这个线程就会结束了。系统会自动对&#8220;<font color="#99cc00">dead</font>&#8221;状态线程进行清理。</p>
<p>&nbsp;&nbsp;&nbsp; 如果一个线程<font color="#99cc00">t1</font>在执行的过程中需要等待另一个线程<font color="#99cc00">t2</font>执行结束后才能运行的话那就可以在<font color="#99cc00">t1</font>在调用<font color="#99cc00">t2</font>的<font color="#99cc00">join()</font>方法</p>
<p><font color="#99cc00">&nbsp;&nbsp;&nbsp; ....<br />
&nbsp;&nbsp;&nbsp; def t1(...):<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ...<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; t2.join()<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ...</font></p>
<p>&nbsp;&nbsp;&nbsp; 这样<font color="#99cc00">t1</font>在执行到<font color="#99cc00">t2.join()</font>语句后就会等待<font color="#99cc00">t2</font>结束后才会继续运行。</p>
<p>&nbsp;&nbsp;&nbsp; 但是假如<font color="#99cc00">t1</font>是个死循环的话那么等待就没有意义了，那怎么办呢？可以在调用<font color="#99cc00">t2</font>的<font color="#99cc00">join()</font>方法的时候给一个浮点数做超时参数，这样这个线程就不会等到花儿也谢了了。我等你10s，你不回来我还不允许我改嫁啊？<font color="#ff0000">:)</font></p>
<p><font color="#99cc00">&nbsp;&nbsp;&nbsp; def t1(...):<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ...<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; t2.join(10)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ...</font></p>
<p>&nbsp;&nbsp;&nbsp; 如果一个进程的主线程运行完毕而子线程还在执行的话，那么进程就不会退出，直到所有子线程结束为止，如何让主线程结束的时候其他子线程也乖乖的跟老大撤退呢？那就要把那些不听话的人设置为听话的小弟，使用线程对象的<font color="#99cc00">setDaemon()</font>方法，参数为<font color="#99cc00">bool</font>型。<font color="#99cc00">True</font>的话就代表你要听话，我老大（主线程）扯呼，你也要跟着撤，不能拖后腿。如果是<font color="#99cc00">False</font>的话就不用那么听话了，老大允许你们将在外军命有所不受的。需要注意的是<font color="#99cc00">setDaemon()</font>方法必须在线程对象没有调用<font color="#99cc00">start()</font>方法之前调用，否则没效果。</p>
<p><font color="#99cc00">&nbsp;&nbsp;&nbsp; t1 = mythread('t1')<br />
&nbsp;&nbsp;&nbsp; print t1.getName(),t1.isDaemon()<br />
&nbsp;&nbsp;&nbsp; t1.setDaemon(True)<br />
&nbsp;&nbsp;&nbsp; print t1.getName(),t1.isDaemon()<br />
&nbsp;&nbsp;&nbsp; t1.start()<br />
&nbsp;&nbsp;&nbsp; print 'main thread exit'</font></p>
<p>&nbsp;&nbsp;&nbsp; 当执行到 <font color="#99cc00">print 'main thread exit' </font>后，主线程就退出了，当然<font color="#99cc00">t1</font>这个线程也跟着结束了。但是如果不使用<font color="#99cc00">t1</font>线程对象的<font color="#99cc00">setDaemon()</font>方法的话，即便主线程结束了，还要等待t1线程自己结束才能退出进程。<font color="#99cc00">isDaemon()</font>是用来获得一个线程对象的<font color="#99cc00">Daemonflag</font>状态的。</p>
<p>&nbsp;&nbsp;&nbsp; 如何来获得与线程有关的信息呢？</p>
<p>&nbsp;&nbsp;&nbsp; 获得当前正在运行的线程的引用</p>
<p><font color="#99cc00">&nbsp;&nbsp;&nbsp; running = threading.currentThread()</font></p>
<p>&nbsp;&nbsp;&nbsp; 获得当前所有活动对象（即<font color="#99cc00">run</font>方法开始但是未终止的任何线程）的一个列表</p>
<p><font color="#99cc00">&nbsp;&nbsp;&nbsp; threadlist = threading.enumerate()</font></p>
<p>&nbsp;&nbsp;&nbsp; 获得这个列表的长度</p>
<p><font color="#99cc00">&nbsp;&nbsp;&nbsp; threadcount = threading.activeCount()</font></p>
<p>&nbsp;&nbsp;&nbsp; 查看一个线程对象的状态调用这个线程对象的<font color="#99cc00">isAlive()</font>方法，返回1代表处于&#8220;<font color="#99cc00">runnable</font>&#8221;状态且没有&#8220;<font color="#99cc00">dead</font>&#8221;</p>
<p><font color="#99cc00">&nbsp;&nbsp;&nbsp; threadflag = threading.isAlive()</font><br />
</p><img src ="http://www.blogjava.net/rain1102/aggbug/148073.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/rain1102/" target="_blank">Eric.Chau</a> 2007-09-25 16:01 <a href="http://www.blogjava.net/rain1102/articles/148073.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>使用Queue实现生产者和消费者</title><link>http://www.blogjava.net/rain1102/articles/148069.html</link><dc:creator>Eric.Chau</dc:creator><author>Eric.Chau</author><pubDate>Tue, 25 Sep 2007 07:51:00 GMT</pubDate><guid>http://www.blogjava.net/rain1102/articles/148069.html</guid><wfw:comment>http://www.blogjava.net/rain1102/comments/148069.html</wfw:comment><comments>http://www.blogjava.net/rain1102/articles/148069.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/rain1102/comments/commentRss/148069.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/rain1102/services/trackbacks/148069.html</trackback:ping><description><![CDATA[<p>from Queue import Queue<br />
import threading<br />
import random<br />
import time</p>
<p>class Producer(threading.Thread):<br />
&nbsp;&nbsp;&nbsp; def __init__(self, threadname, queue):<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; threading.Thread.__init__(self, name=threadname)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.sharedata = queue<br />
&nbsp;&nbsp;&nbsp; def run(self):<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for i in range(10):<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; print self.getName(), 'adding', i, 'to queue'<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.sharedata.put(i)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; time.sleep(random.randrange(10)/10.0)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; print self.getName(), 'Finished'<br />
class Consumer(threading.Thread):<br />
&nbsp;&nbsp;&nbsp; def __init__(self, threadname, queue):<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; threading.Thread.__init__(self, name=threadname)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.sharedata = queue<br />
&nbsp;&nbsp;&nbsp; def run(self):<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for i in range(10):<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; print self.getName(), 'get a value', self.sharedata.get()<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; time.sleep(random.randrange(10)/10.0)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; print self.getName(), 'Finished'<br />
def main():<br />
&nbsp;&nbsp;&nbsp; queue = Queue()<br />
&nbsp;&nbsp;&nbsp; producer = Producer('Producer', queue)<br />
&nbsp;&nbsp;&nbsp; consumer = Consumer('Consumer', queue)<br />
&nbsp;&nbsp;&nbsp; print 'Starting threads...'<br />
&nbsp;&nbsp;&nbsp; producer.start()<br />
&nbsp;&nbsp;&nbsp; consumer.start()<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; producer.join()<br />
&nbsp;&nbsp;&nbsp; consumer.join()<br />
&nbsp;&nbsp;&nbsp; print 'All threads have terminated.'<br />
&nbsp;&nbsp;&nbsp; <br />
if __name__ == '__main__':<br />
&nbsp;&nbsp;&nbsp; main()<br />
<br />
<br />
</p>
<p>如何来获得与线程有关的信息呢？</p>
<p>获得当前正在运行的线程的引用</p>
<p><font color="#99cc00">running = threading.currentThread()</font></p>
<p>获得当前所有活动对象（即<font color="#99cc00">run</font>方法开始但是未终止的任何线程）的一个列表</p>
<p><font color="#99cc00">threadlist = threading.enumerate()</font></p>
<p>获得这个列表的长度</p>
<p><font color="#99cc00">threadcount = threading.activeCount()</font></p>
<p>查看一个线程对象的状态调用这个线程对象的<font color="#99cc00">isAlive()</font>方法，返回1代表处于&#8220;<font color="#99cc00">runnable</font>&#8221;状态且没有&#8220;<font color="#99cc00">dead</font>&#8221;</p>
<p><font color="#99cc00">threadflag = threading.isAlive()</font><br />
</p><img src ="http://www.blogjava.net/rain1102/aggbug/148069.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/rain1102/" target="_blank">Eric.Chau</a> 2007-09-25 15:51 <a href="http://www.blogjava.net/rain1102/articles/148069.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Python中的线程（转载）</title><link>http://www.blogjava.net/rain1102/articles/148043.html</link><dc:creator>Eric.Chau</dc:creator><author>Eric.Chau</author><pubDate>Tue, 25 Sep 2007 05:50:00 GMT</pubDate><guid>http://www.blogjava.net/rain1102/articles/148043.html</guid><wfw:comment>http://www.blogjava.net/rain1102/comments/148043.html</wfw:comment><comments>http://www.blogjava.net/rain1102/articles/148043.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/rain1102/comments/commentRss/148043.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/rain1102/services/trackbacks/148043.html</trackback:ping><description><![CDATA[<div class="subtable altbg2 t_msg" style="width: auto; height: auto"><strong>python线程HelloWorld</strong><br />
<br />
改变num的值可以控制线程的数量<br />
弄它几千个不是问题<br />
呵呵<br />
每个线程启动后会随机睡眠1-3秒<br />
醒来后结束<br />
<br />
[code]<br />
#!/usr/bin/env python<br />
import threading<br />
import time<br />
import random<br />
<br />
class PrintThread(threading.Thread):<br />
&nbsp; &nbsp; def __init__(self, threadName):<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;threading.Thread.__init__(self, name = threadName)<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;self.sleepTime = random.randint(1,3)<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;print "Name: %s; sleep: %d" % (self.getName(), self.sleepTime)<br />
<br />
&nbsp; &nbsp; def run(self):<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;print "%s going to sleep for %s second(s)"\<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;% (self.getName(), self.sleepTime)<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;time.sleep(self.sleepTime)<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;print self.getName(), 'done sleeping'<br />
<br />
num=10<br />
threadList=[]<br />
for i in range(1,num+1):<br />
&nbsp; &nbsp; thread = PrintThread('thread'+str(i))<br />
&nbsp; &nbsp; threadList.append(thread)<br />
<br />
print '\nStarting threads'<br />
<br />
for i in threadList:<br />
&nbsp; &nbsp; i.start()<br />
<br />
print 'All threads started\n'<br />
<br />
for i in threadList:<br />
&nbsp; &nbsp; i.join()<br />
<br />
print 'All threads stoped\n'<br />
[/code]<br />
<br />
线程同步可以用锁<br />
现在让我们一起回到遥远的DOS时代<br />
还是上面的程序<br />
但是每一时刻只有一个线程可以工作<br />
只是增加了三行代码而已<br />
<br />
[code]<br />
#!/usr/bin/env python<br />
import threading<br />
import time<br />
import random<br />
<br />
class PrintThread(threading.Thread):<br />
&nbsp; &nbsp; def __init__(self, threadName):<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;threading.Thread.__init__(self, name = threadName)<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;self.sleepTime = random.randint(1,3)<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;print "Name: %s; sleep: %d" % (self.getName(), self.sleepTime)<br />
<br />
&nbsp; &nbsp; def run(self):<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;lock.acquire()&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;#add this<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;print "%s going to sleep for %s second(s)"\<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;% (self.getName(), self.sleepTime)<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;time.sleep(self.sleepTime)<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;print self.getName(), 'done sleeping'<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;lock.release()&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;#add this<br />
<br />
num=10<br />
threadList=[]<br />
lock=threading.RLock()&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;#add this<br />
for i in range(1,num+1):<br />
&nbsp; &nbsp; thread = PrintThread('thread'+str(i))<br />
&nbsp; &nbsp; threadList.append(thread)<br />
<br />
print '\nStarting threads'<br />
<br />
for i in threadList:<br />
&nbsp; &nbsp; i.start()<br />
<br />
print 'All threads started\n'<br />
<br />
for i in threadList:<br />
&nbsp; &nbsp; i.join()<br />
<br />
print 'All threads stoped\n'<br />
[/code]<br />
</div><img src ="http://www.blogjava.net/rain1102/aggbug/148043.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/rain1102/" target="_blank">Eric.Chau</a> 2007-09-25 13:50 <a href="http://www.blogjava.net/rain1102/articles/148043.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>使用Python操作MySQL</title><link>http://www.blogjava.net/rain1102/articles/148037.html</link><dc:creator>Eric.Chau</dc:creator><author>Eric.Chau</author><pubDate>Tue, 25 Sep 2007 05:22:00 GMT</pubDate><guid>http://www.blogjava.net/rain1102/articles/148037.html</guid><wfw:comment>http://www.blogjava.net/rain1102/comments/148037.html</wfw:comment><comments>http://www.blogjava.net/rain1102/articles/148037.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/rain1102/comments/commentRss/148037.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/rain1102/services/trackbacks/148037.html</trackback:ping><description><![CDATA[首先下载MySQLdb，地址：http://sourceforge.net/projects/mysql-python/<br />
<p>1.&nbsp;&nbsp;&nbsp;使用<br />
&nbsp;&nbsp;&nbsp;&nbsp;import MySQLdb<br />
1.1.&nbsp;&nbsp;&nbsp;连接<br />
&nbsp;&nbsp;&nbsp;&nbsp;conn =&nbsp;&nbsp;&nbsp;MySQLdb.Connection(host, user, password, dbname)<br />
1.2.&nbsp;&nbsp;&nbsp;选择数据库，如果上面没有指定数据库，则使用此方法指定！<br />
&nbsp;&nbsp;&nbsp;&nbsp;conn.select_db(&#8217;database name&#8217;)<br />
1.3.&nbsp;&nbsp;&nbsp;获得cursor<br />
&nbsp;&nbsp;&nbsp;&nbsp;cur =&nbsp;&nbsp;&nbsp;conn.cursor()<br />
1.4.&nbsp;&nbsp;&nbsp;cursor位置设定<br />
&nbsp;&nbsp;&nbsp;&nbsp;cur.scroll(int, mode)<br />
&nbsp;&nbsp;&nbsp;&nbsp;mode可为相对位置或者绝对位置，分别为relative和absolute。<br />
1.5.&nbsp;&nbsp;&nbsp;select<br />
&nbsp;&nbsp;&nbsp;&nbsp;cur.execute(&#8216;select clause&#8217;)<br />
&nbsp;&nbsp;&nbsp;&nbsp;例如<br />
&nbsp;&nbsp;&nbsp;&nbsp;cur.execute(&#8216;select * from mytable&#8217;)</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;row = cur.fetchall()<br />
&nbsp;&nbsp;&nbsp;&nbsp;或者：<br />
&nbsp;&nbsp;&nbsp;&nbsp;row1 = cur.fetchone()<br />
1.6.&nbsp;&nbsp;&nbsp;insert<br />
&nbsp;&nbsp;&nbsp;&nbsp;cur.execute(&#8216;inset clause&#8217;)<br />
&nbsp;&nbsp;&nbsp;&nbsp;例如<br />
&nbsp;&nbsp;&nbsp;&nbsp;cur.execute("insert into user (Name, Password) values ('maggie','12345')")<br />
&nbsp;&nbsp;&nbsp; conn.commit()</p>
<p>1.7.&nbsp;&nbsp;&nbsp;update<br />
&nbsp;&nbsp;&nbsp;&nbsp;cur.execute(&#8216;update&nbsp; clause&#8217;)<br />
&nbsp;&nbsp;&nbsp;&nbsp;例如<br />
&nbsp;&nbsp;&nbsp;&nbsp;cur.execute("update user set Name = 'eric chau' where id = 1")<br />
&nbsp;&nbsp;&nbsp;&nbsp;conn.commit()</p>
<p>1.8.&nbsp;&nbsp;&nbsp;delete<br />
&nbsp;&nbsp;&nbsp;&nbsp;cur.execute(&#8216;delete&nbsp; clause&#8217;)<br />
&nbsp;&nbsp;&nbsp;&nbsp;例如<br />
&nbsp;&nbsp;&nbsp;&nbsp;cur.execute("delete from user where id = 1")<br />
&nbsp;&nbsp;&nbsp;&nbsp;conn.commit()<br />
<br />
<br />
完整代码：<br />
</p>
<p>from MySQLdb import Connect</p>
<p>def conn():<br />
&nbsp;&nbsp;&nbsp; #conn = Connect('localhost','root','root')<br />
&nbsp;&nbsp;&nbsp; #conn.select_db('eric')<br />
&nbsp;&nbsp;&nbsp; conn = Connect('localhost','root','root','eric')<br />
&nbsp;&nbsp;&nbsp; cur = conn.cursor()<br />
&nbsp;&nbsp;&nbsp; cur.execute('select * from user')<br />
&nbsp;&nbsp;&nbsp; cur.scroll(0)<br />
&nbsp;&nbsp;&nbsp; row1 = cur.fetchone()<br />
&nbsp;&nbsp;&nbsp; print 'id:', row1[0]<br />
&nbsp;&nbsp;&nbsp; print 'name:', row1[1]<br />
&nbsp;&nbsp;&nbsp; print 'password:', row1[2]<br />
&nbsp;&nbsp;&nbsp; #cur.execute("insert into user (Name, Password) values ('maggie','12345')")<br />
&nbsp;&nbsp;&nbsp; #cur.execute("update user set Name = 'eric chau' where id = 1")<br />
&nbsp;&nbsp;&nbsp; cur.execute("delete from user where id = 11")<br />
&nbsp;&nbsp;&nbsp; conn.commit()<br />
if __name__=='__main__':<br />
&nbsp;&nbsp;&nbsp; conn()</p><img src ="http://www.blogjava.net/rain1102/aggbug/148037.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/rain1102/" target="_blank">Eric.Chau</a> 2007-09-25 13:22 <a href="http://www.blogjava.net/rain1102/articles/148037.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Django的一些学习资料</title><link>http://www.blogjava.net/rain1102/articles/144526.html</link><dc:creator>Eric.Chau</dc:creator><author>Eric.Chau</author><pubDate>Wed, 12 Sep 2007 08:18:00 GMT</pubDate><guid>http://www.blogjava.net/rain1102/articles/144526.html</guid><wfw:comment>http://www.blogjava.net/rain1102/comments/144526.html</wfw:comment><comments>http://www.blogjava.net/rain1102/articles/144526.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/rain1102/comments/commentRss/144526.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/rain1102/services/trackbacks/144526.html</trackback:ping><description><![CDATA[<strong>中文资料：</strong><br />
<a href="http://www.ibm.com/developerworks/cn/linux/l-django/" target="_blank">Python&nbsp;Web&nbsp;框架，第&nbsp;1&nbsp;部分:&nbsp;使用&nbsp;Django&nbsp;和&nbsp;Python&nbsp;开发&nbsp;Web&nbsp;站点</a><br />
这是一篇介绍Django的入门文章，可以让你对Django有个大致的认识。<br />
<br />
<a href="http://www.woodpecker.org.cn/obp/django/django-stepbystep/newtest/doc/" target="_blank">Django&nbsp;Step&nbsp;by&nbsp;Step</a><br />
limodou大侠的作品，Django入门的绝好资料。<br />
<br />
<a href="http://www.javaeye.com/subject/Django-book?page=2" target="_blank">The&nbsp;Django&nbsp;Book中文翻译</a><br />
<a href="http://www.djangobook.com/" target="_blank">http://www.djangobook.com</a>的中文翻译版，值得一看。<br />
<br />
<strong>英文资料：</strong><br />
<a href="http://www.djangoproject.com/documentation/" target="_blank">Django官方文档</a><br />
首当其冲肯定是这个了，呵呵，有点废话。<br />
<br />
<a href="http://www.djangobook.com/" target="_blank">The&nbsp;Django&nbsp;Book</a><br />
The&nbsp;Django&nbsp;Book的英文原版，喜欢看原版的朋友可以看这个。<br />
<br />
顺便推荐两个Python中文Wiki，这两个Wiki估计很多人都知道，不过也写上来吧，可能有些朋友会有用。<br />
啄木鸟&nbsp;Python&nbsp;开源社区：<a href="http://wiki.woodpecker.org.cn/moin/" target="_blank">http://wiki.woodpecker.org.cn/moin/</a><br />
China&nbsp;Python&nbsp;User&nbsp;Group：<a href="http://python.cn/" target="_blank">http://python.cn/</a> <br /><img src ="http://www.blogjava.net/rain1102/aggbug/144526.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/rain1102/" target="_blank">Eric.Chau</a> 2007-09-12 16:18 <a href="http://www.blogjava.net/rain1102/articles/144526.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>