<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-3102398363073970866</id><updated>2011-04-21T10:40:25.835-07:00</updated><category term='linux'/><category term='twisted'/><category term='python'/><title type='text'>zkfarmer</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://zkfarmer.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3102398363073970866/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://zkfarmer.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>zkfarmer</name><uri>http://www.blogger.com/profile/04680915448070068403</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>9</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-3102398363073970866.post-2172791511159656098</id><published>2009-04-12T03:11:00.000-07:00</published><updated>2009-04-12T03:12:45.447-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='linux'/><title type='text'>Firefox在线听RM.WMA.MP3音乐的解决方法</title><content type='html'>&lt;p&gt;新安装的Firefox2.0.0.1不能播放在线音乐，由于FF缺少插件，又不能像Flashplayer一样在线安装，这时如果你的系统中已经 装了Realplayer和Mplayer（这两个是Linux平台下应该都要装的媒体播放器），我们就可以手动来解决这个问题。&lt;/p&gt; &lt;p&gt;1，到/usr/lib/mozilla/plugins/ 下 这些*.so 的文件都是mplayer for FF的插件, copy它们粘贴它们到你的 firefox/plugins/目录下. 例如/usr/local/firefox2/plugins/&lt;br /&gt;2，同样再到~/realplayer/mozilla/目录下copy nphelix.so到/usr/local/firefox2/plugins/&lt;br /&gt;3，启动FF,在地址栏输入about:plugins, 你会看到已安装的插件’启用’的状态为’是’ ,最后找个在线的音乐试听吧!&lt;/p&gt;&lt;p&gt;http://jatty.szrocket.com/2007/01/02/linux%E4%B8%8Bff%E5%9C%A8%E7%BA%BF%E5%90%ACrmwmamp3/&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3102398363073970866-2172791511159656098?l=zkfarmer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zkfarmer.blogspot.com/feeds/2172791511159656098/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://zkfarmer.blogspot.com/2009/04/firefoxrmwmamp3.html#comment-form' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3102398363073970866/posts/default/2172791511159656098'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3102398363073970866/posts/default/2172791511159656098'/><link rel='alternate' type='text/html' href='http://zkfarmer.blogspot.com/2009/04/firefoxrmwmamp3.html' title='Firefox在线听RM.WMA.MP3音乐的解决方法'/><author><name>zkfarmer</name><uri>http://www.blogger.com/profile/04680915448070068403</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3102398363073970866.post-2291091741021040925</id><published>2009-04-11T10:47:00.000-07:00</published><updated>2009-04-11T10:48:47.420-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='linux'/><title type='text'>永中office,linux下使用宋体</title><content type='html'>拷贝windows操作系统中Windows目录下的Fonts目录中simsun.ttc到/usr/X11R6/lib/X11/fonts/TrueType/中即可。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3102398363073970866-2291091741021040925?l=zkfarmer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zkfarmer.blogspot.com/feeds/2291091741021040925/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://zkfarmer.blogspot.com/2009/04/officelinux.html#comment-form' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3102398363073970866/posts/default/2291091741021040925'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3102398363073970866/posts/default/2291091741021040925'/><link rel='alternate' type='text/html' href='http://zkfarmer.blogspot.com/2009/04/officelinux.html' title='永中office,linux下使用宋体'/><author><name>zkfarmer</name><uri>http://www.blogger.com/profile/04680915448070068403</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3102398363073970866.post-5375283863311012392</id><published>2009-03-24T23:23:00.000-07:00</published><updated>2009-03-24T23:48:27.832-07:00</updated><title type='text'>python 的 函数 vs 方法</title><content type='html'>python中函数和参数有什么不同？函数是实现一个操作的程序段，方法是一个对象运行时带有附加参数的函数。&lt;br /&gt;&lt;br /&gt;例如： class zkfarmer:&lt;br /&gt;                 def  __init__(self, name):&lt;br /&gt;                             self.age = age&lt;br /&gt;                 def  printname(self):&lt;br /&gt;                             return self.name&lt;br /&gt;            def  printage(age):&lt;br /&gt;                  return age&lt;br /&gt;&lt;br /&gt;执行下列语句&lt;br /&gt;myname  = zkfarmer('zkfarmer')&lt;br /&gt;printmyname  = myname.printname()&lt;br /&gt;&lt;br /&gt;printage(100)&lt;br /&gt;&lt;br /&gt;你可能会注意到printname()并没有调用前面的self变量，而事实上如果函数调用中缺少参数，Python会抛出异常－－甚至实际上这个参数也没有什么用处，方法的特别指出就在于把实例对象作为参数的第一个参数传给了函数。调用myname.printname()相当于zkfarmer.printname(myname)。&lt;br /&gt;&lt;br /&gt;方法的工作原理是：把实例对象和函数对象封装成一个抽象的对象：方法对象。以一个参数列表调用方法对象时，它就被重新拆封，用实例对象和原始的参数列表构造一个新的参数列表，然后函数对象调用这个新的参数列表。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3102398363073970866-5375283863311012392?l=zkfarmer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zkfarmer.blogspot.com/feeds/5375283863311012392/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://zkfarmer.blogspot.com/2009/03/python-vs.html#comment-form' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3102398363073970866/posts/default/5375283863311012392'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3102398363073970866/posts/default/5375283863311012392'/><link rel='alternate' type='text/html' href='http://zkfarmer.blogspot.com/2009/03/python-vs.html' title='python 的 函数 vs 方法'/><author><name>zkfarmer</name><uri>http://www.blogger.com/profile/04680915448070068403</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3102398363073970866.post-6173432657414358593</id><published>2009-03-22T03:21:00.000-07:00</published><updated>2009-03-22T03:22:15.926-07:00</updated><title type='text'>python 的脚本与模块</title><content type='html'>&lt;p class="cc-lisence" style="line-height: 180%;"&gt; &lt;a href="http://creativecommons.org/licenses/by/3.0/deed.zh" target="_blank"&gt;版权声明&lt;/a&gt;：转载时请以超链接形式标明文章原始出处和作者信息及&lt;a href="http://bangzhuzhongxin.blogbus.com/logs/11205960.html" target="_blank"&gt;本声明&lt;/a&gt;&lt;br /&gt;&lt;a href="http://norno.blogbus.com/logs/2202802.html"&gt;http://norno.blogbus.com/logs/2202802.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;python的脚本和模块都是以.py结尾的&lt;/p&gt;&lt;p&gt;这样的话 程序是根据什么来判断它是作为脚本还是作为模块？&lt;/p&gt;&lt;p&gt;关键是一个__name__变量(注意前后都是俩个_)&lt;/p&gt;&lt;p&gt;如果它的值是__main__，则是作为脚本运行的&lt;/p&gt;&lt;p&gt;否则是作为模块运行的&lt;/p&gt;&lt;p&gt;if __name__=="__main__":&lt;/p&gt;&lt;p&gt;       main()&lt;/p&gt;&lt;p&gt;这里使用if的原因是每个文件都可能是在另外的程序里被用作库模块&lt;/p&gt;&lt;p&gt;而这个特殊的if只有当你直接运行这个文件的时候才为真&lt;/p&gt;&lt;p&gt;如果这个文件是被另外一个程序当作模块引入的&lt;/p&gt;&lt;p&gt;那么__main__的代码就不会被执行&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3102398363073970866-6173432657414358593?l=zkfarmer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zkfarmer.blogspot.com/feeds/6173432657414358593/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://zkfarmer.blogspot.com/2009/03/python_22.html#comment-form' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3102398363073970866/posts/default/6173432657414358593'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3102398363073970866/posts/default/6173432657414358593'/><link rel='alternate' type='text/html' href='http://zkfarmer.blogspot.com/2009/03/python_22.html' title='python 的脚本与模块'/><author><name>zkfarmer</name><uri>http://www.blogger.com/profile/04680915448070068403</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3102398363073970866.post-4209712579832291280</id><published>2009-03-22T03:17:00.000-07:00</published><updated>2009-03-22T03:18:13.863-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python'/><title type='text'>Python import的一个技巧</title><content type='html'>&lt;p class="cc-lisence" style="line-height: 180%;"&gt; &lt;a href="http://creativecommons.org/licenses/by/3.0/deed.zh" target="_blank"&gt;版权声明&lt;/a&gt;：转载时请以超链接形式标明文章原始出处和作者信息及&lt;a href="http://bangzhuzhongxin.blogbus.com/logs/11205960.html" target="_blank"&gt;本声明&lt;/a&gt;&lt;br /&gt;&lt;a href="http://norno.blogbus.com/logs/2166749.html"&gt;http://norno.blogbus.com/logs/2166749.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;比如我们在a目录下自己写了一个类 在test.py中&lt;/p&gt;&lt;p&gt;在b目录下写的一个程序要调用a目录下的类&lt;/p&gt;&lt;p&gt;其实可以这么操作&lt;/p&gt;&lt;p&gt;import sys&lt;/p&gt;&lt;p&gt;sys.path.append('a目录路径')&lt;/p&gt;&lt;p&gt;import test&lt;/p&gt;&lt;p&gt;这就ok了&lt;/p&gt;&lt;p&gt;其实sys.path就是一个list&lt;/p&gt;&lt;p&gt;比如一般来说&lt;/p&gt;&lt;p&gt;&gt;&gt;&gt; import sys&lt;br /&gt;&gt;&gt;&gt; sys.path&lt;br /&gt;['C:\\Python24\\Lib\\idlelib', 'C:\\WINDOWS\\system32\\python24.zip', 'C:\\Python24', 'C:\\Python24\\DLLs', 'C:\\Python24\\lib', 'C:\\Python24\\lib\\plat-win', 'C:\\Python24\\lib\\lib-tk', 'C:\\Python24\\lib\\site-packages']&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3102398363073970866-4209712579832291280?l=zkfarmer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zkfarmer.blogspot.com/feeds/4209712579832291280/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://zkfarmer.blogspot.com/2009/03/python-import.html#comment-form' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3102398363073970866/posts/default/4209712579832291280'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3102398363073970866/posts/default/4209712579832291280'/><link rel='alternate' type='text/html' href='http://zkfarmer.blogspot.com/2009/03/python-import.html' title='Python import的一个技巧'/><author><name>zkfarmer</name><uri>http://www.blogger.com/profile/04680915448070068403</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3102398363073970866.post-8819022544520570430</id><published>2009-03-22T03:06:00.000-07:00</published><updated>2009-03-22T03:12:55.630-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python'/><title type='text'>python 函数参数的传递</title><content type='html'>&lt;div class="postBody"&gt;                                     &lt;p class="cc-lisence" style="line-height: 180%;"&gt; &lt;a href="http://creativecommons.org/licenses/by/3.0/deed.zh" target="_blank"&gt;版权声明&lt;/a&gt;：转载时请以超链接形式标明文章原始出处和作者信息及&lt;a href="http://bangzhuzhongxin.blogbus.com/logs/11205960.html" target="_blank"&gt;本声明&lt;/a&gt;&lt;br /&gt;&lt;a href="http://norno.blogbus.com/logs/2377663.html"&gt;http://norno.blogbus.com/logs/2377663.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;python中函数参数的传递是通过赋值来传递的。函数参数的使用又有俩个方面值得注意：1.函数参数是如何定义的  2.在调用函数的过程中参数是如何被解析&lt;/p&gt;&lt;p&gt;先看第一个问题，在python中函数参数的定义主要有四种方式：&lt;br /&gt;&lt;span style="color:#ff0000;"&gt;1.F(arg1,arg2,...)&lt;br /&gt;&lt;/span&gt;这 是最常见的定义方式，一个函数可以定义任意个参数，每个参数间用逗号分割，用这种方式定义的函数在调用的的时候也必须在函数名后的小括号里提供个数相等的 值（实际参数），而且顺序必须相同，也就是说在这种调用方式中，形参和实参的个数必须一致，而且必须一一对应，也就是说第一个形参对应这第一个实参。例 如：&lt;br /&gt;def a(x,y):&lt;br /&gt;    print x,y&lt;br /&gt;调用该函数，a(1,2)则x取1，y取2，形参与实参相对应，如果a(1)或者a(1,2,3)则会报错。&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;span style="color:#cc0000;"&gt;2.F(arg1,arg2=value2,...)&lt;/span&gt;&lt;br /&gt;这种方式就是第一种的改进版，提供了默认值&lt;br /&gt;def a(x,y=3):&lt;br /&gt;    print x,y&lt;br /&gt;调用该函数，a(1,2)同样还是x取1，y取2，但是如果a(1)，则不会报错了，这个时候x还是1，y则为默认的3。上面这俩种方式，还可以更换参数位置，比如a(y=8,x=3)用这种形式也是可以的。&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;span style="color:#cc0000;"&gt;3.F(*arg1)&lt;/span&gt;&lt;br /&gt;上 面俩个方式是有多少个形参，就传进去多少个实参，但有时候会不确定有多少个参数，则此时第三种方式就比较有用，它以一个*加上形参名的方式来表示这个函数 的实参个数不定，可能为0个也可能为n个。注意一点是，不管有多少个，在函数内部都被存放在以形参名为标识符的tuple中。&lt;br /&gt;&gt;&gt;&gt; def a(*x):&lt;br /&gt; if len(x)==0:&lt;br /&gt;  print 'None'&lt;br /&gt; else:&lt;br /&gt;  print x&lt;br /&gt;&gt;&gt;&gt; a(1)&lt;br /&gt;(1,)        #存放在元组中&lt;br /&gt;&gt;&gt;&gt; a()&lt;br /&gt;None&lt;br /&gt;&gt;&gt;&gt; a(1,2,3)&lt;br /&gt;(1, 2, 3)&lt;br /&gt;&gt;&gt;&gt; a(m=1,y=2,z=3)&lt;/p&gt;&lt;p&gt;Traceback (most recent call last):&lt;br /&gt;  File "&lt;pyshell#16&gt;", line 1, in -toplevel-&lt;br /&gt;    a(m=1,y=2,z=3)&lt;br /&gt;TypeError: a() got an unexpected keyword argument 'm'&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;span style="color:#cc0000;"&gt;4.F(**arg1)&lt;/span&gt;&lt;br /&gt;形参名前加俩个*表示，参数在函数内部将被存放在以形式名为标识符的dictionary中，这时调用函数的方法则需要采用arg1=value1,arg2=value2这样的形式。&lt;br /&gt;&gt;&gt;&gt; def a(**x):&lt;br /&gt; if len(x)==0:&lt;br /&gt;  print 'None'&lt;br /&gt; else:&lt;br /&gt;  print x &lt;br /&gt;&gt;&gt;&gt; a()&lt;br /&gt;None&lt;br /&gt;&gt;&gt;&gt; a(x=1,y=2)&lt;br /&gt;{'y': 2, 'x': 1}      #存放在字典中&lt;br /&gt;&gt;&gt;&gt; a(1,2)            #这种调用则报错&lt;/p&gt;&lt;p&gt;Traceback (most recent call last):&lt;br /&gt;  File "&lt;pyshell#25&gt;", line 1, in -toplevel-&lt;br /&gt;    a(1,2)&lt;br /&gt;TypeError: a() takes exactly 0 arguments (2 given)&lt;/p&gt;&lt;p&gt;&lt;br /&gt;上面介绍了四种定义方式，接下来看函数参数在调用过程中是怎么被解析的,其实只要记住上面这四种方法优先级依次降低，先1，后2，再3，最后4，&lt;span style="color:#0000ff;"&gt;也就是先把方式1中的arg解析，然后解析方式2中的arg=value，再解析方式3，即是把多出来的arg这种形式的实参组成个tuple传进去，最后把剩下的key=value这种形式的实参组成一个dictionary传给带俩个星号的形参，也就方式4&lt;/span&gt;。&lt;br /&gt;&gt;&gt;&gt; def test(x,y=1,*a,**b):&lt;br /&gt; print x,y,a,b&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&gt;&gt;&gt; test(1)&lt;br /&gt;1 1 () {}&lt;br /&gt;&gt;&gt;&gt; test(1,2)&lt;br /&gt;1 2 () {}&lt;br /&gt;&gt;&gt;&gt; test(1,2,3)&lt;br /&gt;1 2 (3,) {}&lt;br /&gt;&gt;&gt;&gt; test(1,2,3,4)&lt;br /&gt;1 2 (3, 4) {}&lt;br /&gt;&gt;&gt;&gt; test(x=1,y=2)&lt;br /&gt;1 2 () {}&lt;br /&gt;&gt;&gt;&gt; test(1,a=2)&lt;br /&gt;1 1 () {'a': 2}&lt;br /&gt;&gt;&gt;&gt; test(1,2,3,a=4)&lt;br /&gt;1 2 (3,) {'a': 4}&lt;br /&gt;&gt;&gt;&gt; test(1,2,3,y=4)&lt;/p&gt;&lt;p&gt;Traceback (most recent call last):&lt;br /&gt;  File "&lt;pyshell#52&gt;", line 1, in -toplevel-&lt;br /&gt;    test(1,2,3,y=4)&lt;br /&gt;TypeError: test() got multiple values for keyword argument 'y'&lt;/p&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3102398363073970866-8819022544520570430?l=zkfarmer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zkfarmer.blogspot.com/feeds/8819022544520570430/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://zkfarmer.blogspot.com/2009/03/python.html#comment-form' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3102398363073970866/posts/default/8819022544520570430'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3102398363073970866/posts/default/8819022544520570430'/><link rel='alternate' type='text/html' href='http://zkfarmer.blogspot.com/2009/03/python.html' title='python 函数参数的传递'/><author><name>zkfarmer</name><uri>http://www.blogger.com/profile/04680915448070068403</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3102398363073970866.post-3314849682038951651</id><published>2009-03-20T20:29:00.000-07:00</published><updated>2009-03-20T20:31:39.192-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='twisted'/><title type='text'>twisted的异步程序</title><content type='html'>并发程序介绍&lt;br /&gt;&lt;br /&gt;许多计算任务的完成需要相当多的时间，为什么一个任务需要相当多的时间有两个原因：&lt;br /&gt;&lt;br /&gt;1.它是高强度的运算（例如因子分解大量的数目），需要一定的CPU时间来计算答案；&lt;br /&gt;&lt;br /&gt;2.它不是一个高强度的运算，但是不得不为产生一个结果等待可用的数据。&lt;br /&gt;&lt;br /&gt;等待回答&lt;br /&gt;&lt;br /&gt;网络程序一个基本的功能是等待数据。想象你有个发送一个概述一些信息的email的函数，这个函数需要连接到一个远程服务器，等待远程服务器的回复，检查远程服务器可否处理该email，等待回复，发送email，等待确认，然后断开连接。&lt;br /&gt;&lt;br /&gt;这些步骤中的任一个都可能需要很长一段时间。你的程序可以使用所有可能的模型中最简单的，在这种情况下，它实际上坐下并等待数据被发送和接受，但是这种情况中，它有一些明显和根本的局限性：它不能立刻发送多个邮件；并且事实上当它正发送邮件时，不能做其他的任何事情。&lt;br /&gt;&lt;br /&gt;因此，除了最近简单的网络程序外所有的网络程序都避免这种模式。你可以用多中不同模式中的一个，来保持你的程序一直工作，当它正等待一个特定的任务之前发生的一些事情时，任何手边现有的任务都可以继续。&lt;br /&gt;&lt;br /&gt;不等待数据&lt;br /&gt;&lt;br /&gt;编写网络程序有多种方式。主要的是：&lt;br /&gt;&lt;br /&gt;1.用一个分离的操作系统进程处理每个连接，在这种情况中，当一个进程在等待时，操作系统将小心的让其他进程运行；&lt;br /&gt;&lt;br /&gt;2.用一个分离的线程处理每个连接，在这种情况中，当一个线程在等待时，线程框架小心的让其他线程运行；&lt;br /&gt;&lt;br /&gt;3.在一个线程中使用非阻塞系统调用处理所有的连接。&lt;br /&gt;&lt;br /&gt;非阻塞调用&lt;br /&gt;&lt;br /&gt;当使用Twisted框架时通常的模块是第三个模块：非阻塞调用。&lt;br /&gt;&lt;br /&gt;当在一个线程中处理多个连接时，调度是应用程序的职责，而不是操作系统的职责，并且当每个连接准备读取或写入时通过调用一个注册的函数来实现－－通常知名的是asynchronous，event-driven和callback-based程序。&lt;br /&gt;&lt;br /&gt;在这种模型中，早期的email发送函数这样工作：&lt;br /&gt;&lt;br /&gt;1.它调用一个连接函数连接远程的服务器；&lt;br /&gt;&lt;br /&gt;2.该连接函数立即返回，当该连接被建立时，隐含的通知该email发送程序将被调用；&lt;br /&gt;&lt;br /&gt;3.并且一旦连接被建立，连接机制将通知该email发送函数，连接已经就绪。&lt;br /&gt;&lt;br /&gt;上面的顺序覆盖我们原始的阻塞序列有什么好处？好处是当该email发送函数直到连接被打开时不能完成它的工作的下一部分时，程序的其余部分可以完成其他任务，例如为其他email连接开始打开序列。因此，整个程序不再等待连接。&lt;br /&gt;&lt;br /&gt;回调&lt;br /&gt;&lt;br /&gt;典型的异步模块警告一些数据已经就绪就是知名的回调。应用调用一个函数请求一些数据，并且在这个调用中，它也传递一个当数据已经就绪时调用的回调函数作为一个参数。因此该回调函数应该执行该应用需求的数据的任何任务。&lt;br /&gt;&lt;br /&gt;在同步程序中，一个函数请求数据，等待数据，然后处理它，在异步程序中，一个函数请求数据，当数据就绪时让库调用回调函数。&lt;br /&gt;&lt;br /&gt;延迟&lt;br /&gt;&lt;br /&gt;Twisted使用Deferred对象管理回调序列。当异步请求可用时，客户端附加一系列数据给调用的延迟(deferred)（这一些函数就是一系列callbacks，或一个callback chain），在异步请求中如果有一个错误也附加一系列被调用的函数（errbacks和一个errback chain）。当结果可用时，异步库代码调用第一个回调，或者当一个错误发生时调用第一个errback，并且然后Deferred对象管理每个callback或errback函数的结果给链中的下一个函数。&lt;br /&gt;&lt;br /&gt;延迟解决的问题&lt;br /&gt;&lt;br /&gt;并发问题的第二种－－非高强度计算任务涉及一个可见的延迟－－Deferreds被设计用来解决这个问题。等待硬件访问，数据库访问，和网络访问函数都包含在这种情况中，多用时间延迟改变。&lt;br /&gt;&lt;br /&gt;Deferreds被设计用来使Twisted程序等待数据时数据到达前而不用被挂起。它实现这个通过为调用的(程序)库和调用的应用给出一个简单的管理接口。库理解通过调用Deferred.callback&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3102398363073970866-3314849682038951651?l=zkfarmer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zkfarmer.blogspot.com/feeds/3314849682038951651/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://zkfarmer.blogspot.com/2009/03/twisted.html#comment-form' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3102398363073970866/posts/default/3314849682038951651'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3102398363073970866/posts/default/3314849682038951651'/><link rel='alternate' type='text/html' href='http://zkfarmer.blogspot.com/2009/03/twisted.html' title='twisted的异步程序'/><author><name>zkfarmer</name><uri>http://www.blogger.com/profile/04680915448070068403</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3102398363073970866.post-3479382460659516866</id><published>2009-03-20T01:07:00.000-07:00</published><updated>2009-03-20T20:46:40.252-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='twisted'/><title type='text'>twisted-api-zkfarmer手册</title><content type='html'>twisted的api手册，官方只有在线版本的，由于工作需要我做了一份chm格式的手册，和官方的是一致的，给大家放上来。http://www.namipan.com/d/a8ce930ab51a636c93c76e90485c690046c7addf84a94500&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3102398363073970866-3479382460659516866?l=zkfarmer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zkfarmer.blogspot.com/feeds/3479382460659516866/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://zkfarmer.blogspot.com/2009/03/twisted-api-zkfarmer.html#comment-form' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3102398363073970866/posts/default/3479382460659516866'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3102398363073970866/posts/default/3479382460659516866'/><link rel='alternate' type='text/html' href='http://zkfarmer.blogspot.com/2009/03/twisted-api-zkfarmer.html' title='twisted-api-zkfarmer手册'/><author><name>zkfarmer</name><uri>http://www.blogger.com/profile/04680915448070068403</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3102398363073970866.post-1006409790887624397</id><published>2009-03-11T00:52:00.000-07:00</published><updated>2009-03-11T10:26:48.402-07:00</updated><title type='text'>11.11 dircache -- 缓存的目录列表</title><content type='html'>&lt;p&gt;&lt;tt class="module"&gt;dircache&lt;/tt&gt; 模块定义一个使用缓存读取目录列表的函数，并且使用目录的 &lt;var&gt;mtime&lt;/var&gt; 是缓存失效，另外，它定义一个通过附加一个斜线注释是否是目录的函数。  &lt;/p&gt;&lt;p&gt;&lt;tt class="module"&gt;dircache&lt;/tt&gt; 模块定义下列函数：&lt;/p&gt;&lt;dl&gt;&lt;dt&gt;&lt;table cellpadding="0" cellspacing="0"&gt;&lt;tbody&gt;&lt;tr valign="baseline"&gt;   &lt;td&gt;&lt;nobr&gt;&lt;b&gt;&lt;tt id="l2h-2313" class="function"&gt;reset&lt;/tt&gt;&lt;/b&gt;(&lt;/nobr&gt;&lt;/td&gt;   &lt;td&gt;&lt;var&gt;&lt;/var&gt;)&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/dt&gt;&lt;dd&gt;重置目录缓存。 &lt;/dd&gt;&lt;/dl&gt;  &lt;p&gt; &lt;/p&gt;&lt;dl&gt;&lt;dt&gt;&lt;table cellpadding="0" cellspacing="0"&gt;&lt;tbody&gt;&lt;tr valign="baseline"&gt;   &lt;td&gt;&lt;nobr&gt;&lt;b&gt;&lt;tt id="l2h-2314" class="function"&gt;listdir&lt;/tt&gt;&lt;/b&gt;(&lt;/nobr&gt;&lt;/td&gt;   &lt;td&gt;&lt;var&gt;path&lt;/var&gt;)&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/dt&gt;&lt;dd&gt;返回 &lt;var&gt;path&lt;/var&gt; 的目录列表，&lt;tt class="function"&gt;os.listdir()&lt;/tt&gt;一样。注意除非 &lt;var&gt;path&lt;/var&gt; 改变，再次调用 &lt;tt class="function"&gt;listdir()&lt;/tt&gt; 将不在重新读取目录结构。  &lt;p&gt;注意返回的列表应该仅被视为只读。(可能将来的版本可以该变它返回一个元组？) &lt;/p&gt;&lt;/dd&gt;&lt;/dl&gt;  &lt;p&gt; &lt;/p&gt;&lt;dl&gt;&lt;dt&gt;&lt;table cellpadding="0" cellspacing="0"&gt;&lt;tbody&gt;&lt;tr valign="baseline"&gt;   &lt;td&gt;&lt;nobr&gt;&lt;b&gt;&lt;tt id="l2h-2315" class="function"&gt;opendir&lt;/tt&gt;&lt;/b&gt;(&lt;/nobr&gt;&lt;/td&gt;   &lt;td&gt;&lt;var&gt;path&lt;/var&gt;)&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/dt&gt;&lt;dd&gt;同&lt;tt class="function"&gt;listdir()&lt;/tt&gt;一样。它的定义是为了向后的兼容性。 &lt;/dd&gt;&lt;/dl&gt;  &lt;p&gt; &lt;/p&gt;&lt;dl&gt;&lt;dt&gt;&lt;table cellpadding="0" cellspacing="0"&gt;&lt;tbody&gt;&lt;tr valign="baseline"&gt;   &lt;td&gt;&lt;nobr&gt;&lt;b&gt;&lt;tt id="l2h-2316" class="function"&gt;annotate&lt;/tt&gt;&lt;/b&gt;(&lt;/nobr&gt;&lt;/td&gt;   &lt;td&gt;&lt;var&gt;head, list&lt;/var&gt;)&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/dt&gt;&lt;dd&gt;假定 &lt;var&gt;list&lt;/var&gt; 是相对于 &lt;var&gt;head&lt;/var&gt; 的路径的一个列表，并且在合适的位置，每一个指向目录的路径都会被添加一个  "&lt;tt class="character"&gt;/&lt;/tt&gt;" 。&lt;/dd&gt;&lt;/dl&gt;&lt;div class="verbatim"&gt;&lt;pre&gt;&gt;&gt;&gt; import dircache&lt;br /&gt;&gt;&gt;&gt; a = dircache.listdir('/')&lt;br /&gt;&gt;&gt;&gt; a = a[:] # Copy the return value so we can change 'a'&lt;br /&gt;&gt;&gt;&gt; a&lt;br /&gt;['bin', 'boot', 'cdrom', 'dev', 'etc', 'floppy', 'home', 'initrd', 'lib', 'lost+&lt;br /&gt;found', 'mnt', 'proc', 'root', 'sbin', 'tmp', 'usr', 'var', 'vmlinuz']&lt;br /&gt;&gt;&gt;&gt; dircache.annotate('/', a)&lt;br /&gt;&gt;&gt;&gt; a&lt;br /&gt;['bin/', 'boot/', 'cdrom/', 'dev/', 'etc/', 'floppy/', 'home/', 'initrd/', 'lib/&lt;br /&gt;', 'lost+found/', 'mnt/', 'proc/', 'root/', 'sbin/', 'tmp/', 'usr/', 'var/', 'vm&lt;br /&gt;linuz']&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;  &lt;p&gt;  &lt;/p&gt;  &lt;p&gt;由&lt;a href="http://www.zkfarmer.org"&gt;zkfarmer&lt;/a&gt;翻译整理。&lt;br /&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3102398363073970866-1006409790887624397?l=zkfarmer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zkfarmer.blogspot.com/feeds/1006409790887624397/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://zkfarmer.blogspot.com/2009/03/1111-dircache.html#comment-form' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3102398363073970866/posts/default/1006409790887624397'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3102398363073970866/posts/default/1006409790887624397'/><link rel='alternate' type='text/html' href='http://zkfarmer.blogspot.com/2009/03/1111-dircache.html' title='11.11 dircache -- 缓存的目录列表'/><author><name>zkfarmer</name><uri>http://www.blogger.com/profile/04680915448070068403</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry></feed>
