Differences between revisions 18 and 19
Revision 18 as of 2008-04-27 02:54:45
Size: 29120
Editor: lizzie
Comment:
Revision 19 as of 2008-04-27 05:00:06
Size: 28971
Editor: lizzie
Comment:
Deletions are marked like this. Additions are marked like this.
Line 14: Line 14:
'''cdays-5-exercise-1.py this year is a leap year or not '''cdays-5-exercise-1.py 判断今年是否是闰年
Line 30: Line 30:
'''cdays-5-exercise-2.py basic operation and math library '''cdays-5-exercise-2.py 基本表达式运算及使用math模块
Line 57: Line 57:
'''cdays-5-exercise-3.py print out and for expression '''cdays-5-exercise-3.py for语句的使用
Line 131: Line 131:
'''cdays-4-exercise-6.py file operation '''cdays-4-exercise-6.py 文件操作
Line 203: Line 203:
Line 209: Line 208:
'''cdays-3-exercise-2.py using sys.args, dict and function invoke '''cdays-3-exercise-2.py 使用sys.args, dict和函数调用
Line 215: Line 214:
 ''' function collect: change the key-value to value-key
 @param file: file object
 @return: a dict type, get the value-key pairs
 ''' 改变 key-value对为value-key
 @param file: 文件对象
 @return: 一个dict包含value-key
Line 248: Line 247:
'''cdays-3-exercise-3.py using global varibles, invoke function recursively '''cdays-3-exercise-3.py 使用全局变量和函数递归调用
Line 258: Line 257:
 ''' function output: print out one state  ''' 输出一种有效结果
Line 265: Line 264:
 ''' function do_queen: generate all states of queens' position
 @param i: the number of queen
 ''' 生成所有正确解
 @param i: 皇后的数目
Line 371: Line 370:
'''cdays-2-exercise-2.py using class and object '''cdays-2-exercise-2.py 类和对象的使用
Line 376: Line 375:
  user-defined stack, has basic stack operations, such as put(), get() and isEmpty()   自定义栈,主要操作有put(), get() and isEmpty()
Line 380: Line 379:
  init the stack: the head of stack and empty the stack
  @param max: specify the max length of stack
  初始化栈:初始栈头指针和清空栈
  @param max: 指定栈的最大长度
Line 391: Line 390:
  put item into the stack
  @param item: anything want to put the current stack
  将item压入栈中
  @param item: 所要入栈的项
Line 405: Line 404:
  get the top item of current stack
  @return: the top item
  获得当前栈顶item
  @return: 栈顶item
Line 419: Line 418:
  get the state of current stack
  @return: True(the stack is empty) or False(else)
  获得当前栈的状态,空或者非空
  @return: True(栈空) or False(栈非空)
Line 445: Line 444:
'''cdays-1-exercise-1.py using chardet and urllib2 '''cdays-1-exercise-1.py 使用chardeturllib2
Line 454: Line 453:
 detect the coding of blog
 @param blogurl: some url string
 检测blog的编码方式
 @param blogurl: 要检测blog的url
Line 479: Line 478:
Line 485: Line 483:
'''cdays-1-exercise-2.py using chardet, urllib2 '''cdays-1-exercise-2.py 熟悉chardeturllib2
Line 493: Line 491:
 detect the coding of blog and save the blog in utf-8
 @param blogurl: some url string
 检测blog的编码方式
 @param blogurl: 要检测blog的url
Line 529: Line 527:
Line 569: Line 566:
'''cdays+1-exercise-1.py using os.stat '''cdays+1-exercise-1.py 使用os.stat获取相关信息
Line 575: Line 572:
 ''' get the three big size of files in the path
 @param path: specify the files of path
 @return one list contains item like (size, filename)
 ''' 获取给定路径中文件大小最大的三个
 @param path: 指定路径
 @return 返回一个list,每项为 (size, filename)
Line 622: Line 619:
'''cdays+1-exercise-2.py using ConfigParser '''cdays+1-exercise-2.py 使用ConfigParser解析
Line 646: Line 643:
 ''' get the three big size of files in the path
 @param path: specify the files of path
 @return one list contains item like (size, filename)
 ''' 获取给定路径中文件大小最大的三个
 @param path: 指定路径
 @return 返回一个list,每项为 (size, filename)
Line 697: Line 694:
Line 699: Line 695:
Line 701: Line 696:
Line 703: Line 697:
Line 720: Line 713:
import pickle # 神奇的序列化模块 import pickle        # 神奇的序列化模块
Line 781: Line 774:
Line 791: Line 783:
'''cdays+3-exercise-1.py using Thread and RLock '''cdays+3-exercise-1.py 使用ThreadRLock实现简单线程同步
Line 799: Line 791:
  user-defined thread   自定义的线程,多个线程共同访问一个变量
Line 827: Line 819:
Line 833: Line 824:
'''cdays+3-exercise-2.py using Thread and Queue
    @author: U{shengyan<mailto:[email protected]>}
    @version:$Id$
'''cdays+3-exercise-2.py 使用Thread和Queue保持多线程间同步
Line 842: Line 831:
 '''Input Thread: read one string from stdio, then add this string into queue  '''输入线程: 从标准输入中读一个string,然后把该string加入到queue
Line 856: Line 845:
 '''Output Thread: read one string from queue, then print it out  '''输出线程:从queue中得到一个string,并将它输出到屏幕
Line 887: Line 876:
Line 893: Line 881:
'''cdays+3-exercise-3.py using Thread and Event '''cdays+3-exercise-3.py 使用ThreadEvent实现简单的线程通信
Line 901: Line 889:
  user-defined thread   自定义线程

status

校对

ShengYan

完成度70%

TableOfContents

1. 故事练习解答

1.1. CDays

1.1.1. CDays-5

  • 计算今年是闰年嘛?

   1 #coding:utf-8
   2 '''cdays-5-exercise-1.py 判断今年是否是闰年
   3 '''
   4 #导入time模块
   5 import time
   6 #获取当前年份
   7 thisyear = time.localtime()[0]
   8 #判断闰年条件,满足模400为0,或者模4为0但模100不为0
   9 if thisyear % 400 == 0 or thisyear % 4 ==0 and thisyear % 100 <> 0:
  10         print 'this year %s is a leap year' % thisyear
  11 else:
  12         print 'this year %s is not a leap year' % thisyear
  • 利用python作为科学计算器。熟悉Python中的常用运算符,并分别求出表达式12*34+78-132/6、(12*(34+78)-132)/6、(8.6/4)**5的值。并利用math模块进行数学计算,分别求出145/23的余数,0.5的sin和cos值等等,详细可参考help(math)。

   1 #coding:utf-8
   2 '''cdays-5-exercise-2.py 基本表达式运算及使用math模块
   3 '''
   4 #表达式计算
   5 x = 12*34+78-132/6
   6 y = (12*(34+78)-132)/6
   7 z = (8.6/4)**5
   8 print '12*34+78-132/6 = %d' % x
   9 print '(12*(34+78)-132)/6 = %d' % y
  10 print '(8.6/4)**5 = %f' % z
  11 #导入数学计算模块
  12 import math
  13 #求余函数
  14 a = math.fmod(145, 23)
  15 #正弦函数
  16 b = math.sin(0.5)
  17 #余弦函数
  18 c = math.cos(0.5)
  19 print '145/23的余数 = %d' % a
  20 print 'sin(0.5) = %f' %b
  21 print 'cos(0.5) = %f' %c
  • 编写程序,在屏幕上打印出如下图案: attachment:cdays-5-exercise-3.png

   1 #coding:utf-8
   2 '''cdays-5-exercise-3.py for语句的使用
   3 '''
   4 for index in range(1, 6):
   5         if index > 3:
   6                 #调整index
   7                 index = 2*3 -index
   8         #输出每行空格个数
   9         print ' '*(3-index),
  10         #输出每行*的个数
  11         print '*'*(2*index - 1)
  • 运行结果截图 attachment:cdays-5-exercise-123.png

1.1.2. CDays-4

  • os 模块中还有哪些功能可以使用? -- 提示使用 dir() help()

    1. os.error, os.path, os.popen, os.stat_result, os.sys, os.system等等等
    2. 详细可参见dir(os)和python帮助文档help(os)

  • open() 还有哪些模式可以使用?

    1. 'r': 以只读方式打开已存在文件,若文件不存在则抛出异常。此方式是默认方式
    2. 'U'或者'rU': python惯例构造了通用换行支持;提供'U'模式以文本方式打开一个文件,但是行可能随时结束:Unix的结束符规定为'\n',苹果系统则为'\r',还有windows规定为'\r\n',所有这些规定在python程序中统一为'\n'.如果python不构造一个通用换行支持模式'u'来用统一对待正常文本模式的话
    3. 'w': 以可写方式打开存在或者不存在的文件,若文件不存在则先新建该文件,若文件存在则覆盖该文件
    4. 'a': 用于追加,对unix系统而言,所有的内容都将追加到文件末尾而不管指针的当前位置如何
    5. 'b': 以二进制方式打开。打开一个二进制文件必须用该模式。增加'b'模式是用来兼容系统对当二进制和文本文件的处理不同
    6. 'r+','w+'和'a+'以更新方式打开文件(注意'w+'覆盖文件)
  • 尝试for .. in .. 循环可以对哪些数据类型进行操作?

    1. for..in循环对于任何序列(列表,元组,字符串)都适用。但从广义说来可以使用任何种类的由任何对象组成的序列
  • 格式化声明,还有哪些格式可以进行约定?
    • 详细参考:http://docs.python.org/lib/typesseq-strings.html

    • d Signed integer decimal.
    • i Signed integer decimal.
    • o Unsigned octal.
    • u Unsigned decimal.
    • x Unsigned hexadecimal (lowercase).
    • X Unsigned hexadecimal (uppercase).
    • e Floating point exponential format (lowercase).
    • E Floating point exponential format (uppercase).
    • f Floating point decimal format.
    • F Floating point decimal format.
    • g Floating point format. Uses exponential format if exponent is greater than -4 or less than precision, decimal format otherwise.
    • G Floating point format. Uses exponential format if exponent is greater than -4 or less than precision, decimal format otherwise.
    • c Single character (accepts integer or single character string).
    • r String (converts any python object using repr()).
    • s String (converts any python object using str()).
    • % No argument is converted, results in a "%" character in the result.
  • 现在的写入文件模式好嘛? 有改进的余地?
    1. CDay-4-5.py中使用了字符串的+连接,而CDay-4-6.py中是利用join。字符串的join要比'+'操作效率高。因为对象的反复+,比一次性内建处理,要浪费更多的资源。

CDay-4-5.py 好在哪里? :

   1 # coding : utf-8
   2 import os
   3 export = ""
   4 for root, dirs, files in os.walk('/media/cdrom0'):
   5   export+="\n %s;%s;%s" % (root,dirs,files)
   6 open('mycd2.cdc', 'w').write(export)

CDay-4-6.py 又更加好在哪里? :

   1 # coding : utf-8
   2 import os
   3 export = []
   4 for root, dirs, files in os.walk('/media/cdrom0'):
   5     export.append("\n %s;%s;%s" % (root,dirs,files))
   6 open('mycd2.cdc', 'w').write(''.join(export))
  • 读取文件cdays-4-test.txt内容,去除空行和注释行后,以行为单位进行排序,并将结果输出为cdays-4-result.txt。

   1 #coding:utf-8
   2 '''cdays-4-exercise-6.py 文件操作
   3 '''
   4 #以读方式打开文件
   5 f = open('cdays-4-test.txt', 'r')
   6 result = list()
   7 #依次读取每行
   8 for line in f.readlines():
   9         #去掉每行头尾空白
  10         line = line.strip()
  11         #判断是否是空行或注释行
  12         if not len(line) or line.startswith('#'):
  13                 #是的话,跳过不处理
  14                 continue
  15         result.append(line)
  16 #排序结果
  17 result.sort()
  18 #保存入结果文件
  19 open('cdays-4-result.txt', 'w').write('%s' % '\n'.join(result)) 
  • 运行结果截图 attachment:cdays-4-exercise-6.png

1.1.3. CDays-3

   1 # coding=utf-8
   2 '''Lovely Python -3 PyDay 
   3     PyCDC v0.3
   4 '''
   5 import os,sys
   6 import getopt
   7 
   8 CDROM = '/media/cdrom0'
   9 def cdWalker(cdrom,cdcfile):
  10         export = ""
  11         for root, dirs, files in os.walk(cdrom):
  12                 export+="\n %s;%s;%s" % (root,dirs,files)
  13         open(cdcfile, 'w').write(export)
  14 
  15 def usage():
  16         print '''PyCDC 使用方式:
  17         python cdays-3-exercise-1.py -d cdc -k 中国火
  18         #搜索 cdc 目录中的光盘信息,寻找有“中国火”字样的文件或是目录,在哪张光盘中
  19         '''
  20 
  21 try:
  22         opts, args = getopt.getopt(sys.argv[1:], 'hd:e:k:')
  23 except getopt.GetoptError:
  24         usage()
  25         sys.exit()
  26 
  27 if len(opts) == 0:
  28         usage()
  29         sys.exit()
  30 
  31 c_path = ''
  32 for opt, arg in opts:
  33         if opt in ('-h', '--help'):
  34                 usage()
  35                 sys.exit()
  36         elif opt == '-e':
  37                 #判别sys.argv[2]中是否有目录,以便进行自动创建
  38                 #cdWalker(CDROM, arg)
  39                 print "记录光盘信息到 %s" % arg
  40         elif opt == '-d':
  41                 c_path = arg
  42         elif opt == '-k':
  43                 if not c_path:
  44                         usage()
  45                         sys.exit()
  46                 #进行文件搜索
  • 读取某一简单索引文件cdays-3-test.txt,其每行格式为文档序号 关键词,现需根据这些信息转化为倒排索引,即统计关键词在哪些文档中,格式如下:包含该关键词的文档数 关键词 => 文档序号。其中,原索引文件作为命令行参数传入主程序,并设计一个collect函数统计关键字-序号结果对,最后在主程序中输出结果至屏幕。

   1 #coding:utf-8
   2 '''cdays-3-exercise-2.py 使用sys.args, dict和函数调用
   3 '''
   4 #导入sys模块
   5 import sys
   6 
   7 def collect(file):
   8         ''' 改变 key-value对为value-key对
   9         @param file: 文件对象
  10         @return: 一个dict包含value-key对
  11         '''
  12         result = {}
  13         #依次读取每行
  14         for line in file.readlines():
  15                 #将一行以空格分割为左右两部分
  16                 left, right = line.split()
  17                 #判断是否已经含有right值对应的key
  18                 if result.has_key(right):
  19                         #若有,直接添加到result[right]的值列表
  20                         result[right].append(left)
  21                 else:
  22                         #没有,则新建result[right]的值列表
  23                         result[right] = [left]
  24         return result
  25 
  26 if __name__ == "__main__":
  27         #判断参数个数
  28         if len(sys.argv) == 1:
  29                 print 'usage:\n\tpython cdays-3-exercise-2.py cdays-3-test.txt'
  30         else:
  31                 #调用collect函数,返回结果
  32                 result = collect(open(sys.argv[1], 'r'))
  33                 #输出结果
  34                 for (right, lefts) in result.items():
  35                         print "%d '%s'\t=>\t%s" % (len(lefts), right, lefts)
  • 八皇后问题。在8*8的棋盘上,放置8个皇后,使得任两个皇后不在同行同列同正负对角线上。

   1 #coding:utf-8
   2 '''cdays-3-exercise-3.py 使用全局变量和函数递归调用  
   3 '''
   4 #定义一些全局变量
   5 global col
   6 global row
   7 global pos_diag
   8 global nag_diag
   9 global count
  10 
  11 def output():   
  12         ''' 输出一种有效结果
  13         '''
  14         global count
  15         print row
  16         count += 1
  17 
  18 def do_queen(i):
  19         ''' 生成所有正确解
  20         @param i: 皇后的数目
  21         '''
  22         #依次尝试0~7位置
  23         for j in range(0, 8):
  24                 #若该行,正对角线,负对角线上都没有皇后,则放入i皇后
  25                 if col[j] == 1 and pos_diag[i-j+7] == 1 and nag_diag[i+j] == 1: 
  26                         row[i] = j
  27                         #调整各个列表状态
  28                         col[j] = 0
  29                         pos_diag[i-j+7] = 0
  30                         nag_diag[i+j] = 0
  31                         if i < 7:
  32                                 #可递增或递减
  33                                 do_queen(i+1)
  34                         else:
  35                                 #产生一个结果,输出
  36                                 output()
  37                         #恢复各个列表状态为之前的
  38                         col[j] = 1
  39                         pos_diag[i-j+7] = 1
  40                         nag_diag[i+j] = 1
  41 
  42 if __name__ == '__main__':
  43         #矩阵列的列表,存储皇后所在列,若该列有皇后,则相应置为1,反之则0
  44         col = []
  45         #矩阵行的列表,存放每行皇后所在的位置,随着程序的执行,在不断的变化中,之间输出结果
  46         row = []
  47         #正对角线,i-j恒定,-7~0~7,并且b(i)+7统一到0~14
  48         pos_diag = []
  49         #负对角线,i+j恒定,0~14
  50         nag_diag = []
  51         count = 0
  52         #一些初始化工作
  53         for index in range(0, 8):
  54                 col.append(1)
  55                 row.append(0)
  56         for index in range(0, 15):
  57                 pos_diag.append(1)
  58                 nag_diag.append(1)
  59         #开始递归,先放一个,依次递增,反过来,从7开始递减也可
  60         do_queen(0)
  61         print 'Totally have %d solutions!' % count
  • 运行结果截图 attachment:cdays-3-exercise-123.png

1.1.4. CDays-2

  • 把最后探索出的 cdcGrep()嵌入 pycdc-v0.5.py 实现完成版本的 PyCDC

   1 # coding= utf-8
   2 '''pycdc-v0.5.py
   3 Lovely Python -2 PyDay 
   4 '''
   5 import sys, cmd
   6 from cdctools import *
   7 class PyCDC(cmd.Cmd):
   8     def __init__(self):
   9         cmd.Cmd.__init__(self)                # initialize the base class
  10         self.CDROM = '/media/cdrom0'
  11         self.CDDIR = 'cdc/'
  12         self.prompt="(PyCDC)>"
  13         self.intro = '''PyCDC0.5 使用说明:
  14     dir 目录名     #指定保存和搜索目录,默认是 "cdc"
  15     walk 文件名    #指定光盘信息文件名,使用 "*.cdc"
  16     find 关键词    #遍历搜索目录中所有.cdc文件,输出含有关键词的行
  17     ?           # 查询
  18     EOF         # 退出系统,也可以使用Crtl+D(Unix)|Ctrl+Z(dos/windows)
  19         '''
  20 
  21     def help_EOF(self):
  22         print "退出程序 Quits the program"
  23     def do_EOF(self, line):
  24         sys.exit()
  25 
  26     def help_walk(self):
  27         print "扫描光盘内容 walk cd and export into *.cdc"
  28     def do_walk(self, filename):
  29         if filename == "":filename = raw_input("输入cdc文件名:: ")
  30         print "扫描光盘内容保存到:'%s'" % filename
  31         cdWalker(self.CDROM,self.CDDIR+filename)
  32 
  33     def help_dir(self):
  34         print "指定保存/搜索目录"
  35     def do_dir(self, pathname):
  36         if pathname == "": pathname = raw_input("输入指定保存/搜索目录: ")
  37         self.CDDIR = pathname
  38         print "指定保存/搜索目录:'%s' ;默认是:'%s'" % (pathname,self.CDDIR)
  39 
  40     def help_find(self):
  41         print "搜索关键词"
  42     def do_find(self, keyword):
  43         if keyword == "": keyword = raw_input("输入搜索关键字: ")
  44         print "搜索关键词:'%s'" % keyword
  45         cdcGrep(self.CDDIR,keyword)
  46 
  47 if __name__ == '__main__':      # this way the module can be
  48     cdc = PyCDC()            # imported by other programs as well
  49     cdc.cmdloop()
  • 编写一个类,实现简单的栈。数据的操作按照先进后出(FILO)的顺序。主要成员函数为put(item),实现数据item插入栈中;get(),实现从栈中取一个数据。

   1 #coding:utf-8
   2 '''cdays-2-exercise-2.py 类和对象的使用
   3 '''
   4 
   5 class MyStack(object):
   6         '''MyStack
   7                 自定义栈,主要操作有put(), get() and isEmpty()
   8         '''
   9         def __init__(self, max):
  10                 '''
  11                 初始化栈:初始栈头指针和清空栈
  12                 @param max: 指定栈的最大长度
  13                 '''
  14                 self.head = -1
  15                 self.stack = list()
  16                 self.max = max
  17                 for i in range(self.max):
  18                         self.stack.append(0)
  19         
  20         def put(self, item):
  21                 '''
  22                 将item压入栈中
  23                 @param item: 所要入栈的项
  24                 '''
  25                 #判断当前栈是否满了
  26                 if self.head >= self.max:
  27                         #提示栈溢出
  28                         return 'Put Error: The Stack is Overflow!'
  29                 else:
  30                         #不满,则将item入栈,调整栈顶指针
  31                         self.head += 1
  32                         self.stack[self.head] = item
  33         
  34         def get(self):
  35                 '''
  36                 获得当前栈顶item
  37                 @return: 栈顶item
  38                 '''
  39                 #判断当前栈是否为空
  40                 if self.head < 0:
  41                         #提示栈空
  42                         return 'Get Error: The Stack is Empty!' 
  43                 else:
  44                         #出栈,返回栈顶元素,并调整栈顶指针
  45                         self.head -= 1  
  46                         return self.stack[self.head+1]
  47         
  48         def isEmpty(self):
  49                 '''
  50                 获得当前栈的状态,空或者非空
  51                 @return: True(栈空) or False(栈非空)
  52                 '''
  53                 if self.head < -1:
  54                         return True
  55                 return False
  56 
  57 if __name__ == "__main__":
  58         mystack = MyStack(100)
  59         mystack.put('a')
  60         mystack.put('b')
  61         print mystack.get()
  62         mystack.put('c')
  63         print mystack.get()
  64         print mystack.get()
  65         print mystack.get()
  • 运行结果截图 attachment:cdays-2-exercise-12.png

1.1.5. CDays-1

  • 自动判定你自个儿的Blog 是什么编码的?

   1 #coding:utf-8
   2 '''cdays-1-exercise-1.py 使用chardet和urllib2
   3 '''
   4 
   5 import sys
   6 import urllib2
   7 import chardet
   8 
   9 def blog_detect(blogurl):
  10         '''
  11         检测blog的编码方式
  12         @param blogurl: 要检测blog的url
  13         '''
  14         try:
  15                 #尝试打开给定url
  16                 fp = urllib2.urlopen(blogurl)
  17         except Exception, e:
  18                 #若产生异常,则给出相关提示并返回
  19                 print e
  20                 print 'download exception %s' % blogurl
  21                 return 0
  22         #读取内容
  23         blog = fp.read()
  24         #检测得到编码方式
  25         codedetect = chardet.detect(blog)["encoding"]
  26         print '%s\t<-\t%s' % (blogurl, codedetect)
  27         #关闭
  28         fp.close()
  29         return 1
  30     
  31 if __name__ == "__main__":
  32         if len(sys.argv) == 1:
  33                 print 'usage:\n\tpython cdays-1-exercise-1.py http://xxxx.com'
  34         else:
  35                 blog_detect(sys.argv[1])
  • 在题一基础上,如果blog的编码不是utf-8,编写小程序自动将其转换成utf-8 编码保存到本地?

   1 #coding:utf-8
   2 '''cdays-1-exercise-2.py 熟悉chardet和urllib2
   3 '''
   4 import sys
   5 import urllib2
   6 import chardet
   7 
   8 def blog_detect(blogurl):
   9         '''
  10         检测blog的编码方式
  11         @param blogurl: 要检测blog的url
  12         '''
  13         try:
  14                 #尝试打开给定url
  15                 fp = urllib2.urlopen(blogurl)
  16         except Exception, e:
  17                 #若产生异常,则给出相关提示并返回
  18                 print e
  19                 print 'download exception %s' % blogurl
  20                 return 0
  21         #读取内容
  22         blog = fp.read()
  23         fp.close()
  24         #检测得到编码方式
  25         codedetect = chardet.detect(blog)["encoding"]
  26         if codedetect <> 'utf-8':  #是否是utf-8
  27                 try:
  28                         #不是的话,则尝试转换
  29                         blog = unicode(blog, codedetect) 
  30                         blog = blog.encode('utf8')
  31                 except:
  32                         print u"bad unicode encode try!"
  33                         return 0
  34         #保存入文件
  35         filename = '%s_utf-8' % blogurl[7:]
  36         filename = filename.replace('/', '_')
  37         open(filename, 'w').write('%s' % blog)
  38         print 'save to file %s' % filename
  39         return 1
  40     
  41 if __name__ == "__main__":
  42         if len(sys.argv) == 1:
  43                 print 'usage:\n\tpython cdays-1-exercise-2.py http://xxxx.com'
  44         else:
  45                 blog_detect(sys.argv[1])
  • 运行结果截图 attachment:cdays-1-exercise-12.png

1.1.6. CDays-0

  • 请根据软件发布的流程和软件开发的编码规范,将读者之前章节写的程序修改并发布出去。另外,可以查找下除了epydoc外还有哪些较好的py文档生成器?
    • 步骤:
    • 编写epydoc的配置文件,如下cdays0-epydoc.cfg。
    • 在终端中输入epydoc --config cdays0-epydoc.cfg,即可生成文档。

[epydoc] 
# Epydoc section marker (required by ConfigParser)

# Information about the project.
name: MyStack
url: http://wiki.woodpecker.org.cn/moin/ObpLovelyPython

# The list of modules to document.  Modules can be named using
# dotted names, module filenames, or package directory names.
# This option may be repeated.
modules:  ./cdays0-exercise-1.py

# Write html output to the directory "apidocs"
output: html
target: apidocs/

# Include all automatically generated graphs.  These graphs are
# generated using Graphviz dot.
graph: all
dotpath: /usr/bin/dot
  • 运行结果截图 attachment:cdays-0-exercise-1.png

1.1.7. CDays+1

  • 编程实现以下功能并进行最大化的优化:遍历指定目录下的所有文件,找出其中占用空间最大的前3个文件。

   1 #coding:utf-8
   2 '''cdays+1-exercise-1.py 使用os.stat获取相关信息
   3 '''
   4 import sys
   5 import os
   6 
   7 def get_top_three(path):
   8         ''' 获取给定路径中文件大小最大的三个
   9         @param path: 指定路径
  10         @return 返回一个list,每项为 (size, filename)
  11         '''
  12         all_file = {}
  13         #遍历path
  14         for root, dirs, files in os.walk(path):
  15                 for onefile in files:
  16                         #获得当前处理文件的完整名字
  17                         fname = os.path.join(root, onefile)
  18                         #获得当前处理文件大小
  19                         fsize = os.stat(fname).st_size
  20                         #按照文件大小存储
  21                         if all_file.has_key(fsize):
  22                                 all_file[fsize].append(fname)
  23                         else:
  24                                 all_file[fsize] = [fname]
  25         #得到所有的文件大小
  26         fsize_key = all_file.keys()
  27         #排序,从小到大
  28         fsize_key.sort()
  29         result = []
  30         #依次取最大的三个
  31         for i in [-1, -2, -3]:
  32                 for j in all_file[fsize_key[i]]:
  33                         result.append((fsize_key[i], j))
  34         #返回前三个
  35         return result[:3]
  36     
  37 if __name__ == "__main__":
  38         if len(sys.argv) == 1:
  39                 print 'usage:\n\tpython cdays+1-exercise-1.py path'
  40         else:
  41                 #得到绝对路径
  42                 abs_path = os.path.abspath(sys.argv[1])
  43                 #判断所给的路径是否存在
  44                 if not os.path.isdir(abs_path): 
  45                         print '%s is not exist' % abs_path
  46                 else:
  47                         top = get_top_three(abs_path)
  48                         for (s, f) in top:
  49                                 print '%s\t->\t%s' % (s, f)
  • 利用ConfigParser,将上述题目中产生的结果按照cdays+1-my.ini格式存储到文件cdays+1-result.txt中。

   1 #coding:utf-8
   2 '''cdays+1-exercise-2.py 使用ConfigParser解析
   3 '''
   4 import os
   5 import sys
   6 from ConfigParser import RawConfigParser
   7 
   8 def iniTT(size_file):
   9         ''' 按照.ini的格式,存储size_file
  10         '''
  11         cfg = RawConfigParser()
  12         print size_file
  13         index = 1
  14         for (s, f) in size_file:
  15                 #增加一个section
  16                 cfg.add_section("%d" % index)
  17                 #在该section设置Filename及其值
  18                 cfg.set("%d" % index, 'Filename', f)
  19                 #在该section设置FileSize及其值
  20                 cfg.set("%d" % index, 'FileSize', s)
  21                 index += 1
  22 
  23         cfg.write(open('cdays+1-result.txt',"w"))
  24 
  25 def gtt(path):
  26         ''' 获取给定路径中文件大小最大的三个
  27         @param path: 指定路径
  28         @return 返回一个list,每项为 (size, filename)
  29         '''
  30         all_file = {}
  31         #遍历path
  32         for root, dirs, files in os.walk(path): 
  33                 for onefile in files:
  34                         #获得当前处理文件的完整名字
  35                         fname = os.path.join(root, onefile)
  36                         #获得当前处理文件大小
  37                         fsize = os.stat(fname).st_size
  38                         #按照文件大小存储
  39                         if all_file.has_key(fsize):
  40                                 all_file[fsize].append(fname)
  41                         else:
  42                                 all_file[fsize] = [fname]
  43         #得到所有的文件大小
  44         fsize_key = all_file.keys()
  45         #排序,从小到大
  46         fsize_key.sort()
  47         result = []
  48         #依次取最大的三个
  49         for i in [-1, -2, -3]:
  50                 for j in all_file[fsize_key[i]]:#保存
  51                         result.append((fsize_key[i], j))
  52         #返回前三个
  53         return result[:3]
  54 
  55 if __name__ == "__main__":
  56         if len(sys.argv) == 1:
  57                 print 'usage:\n\tpython cdays+1-exercise-2.py path'
  58         else:
  59                 abs_path = os.path.abspath(sys.argv[1])
  60                 if not os.path.isdir(abs_path):
  61                         print '%s is not exist' % abs_path
  62                 else:
  63                         #from cdays+1-exercise-1 import get_top_three as gtt
  64                         iniTT(gtt(abs_path))
  • 运行结果截图 attachment:cdays+1-exercise-12.png

1.1.8. CDays+2

  • 如果在Karrigell 实例中,不复制 cdctools.py 到webapp 目录中,也可以令 index.ks 引用到?
    1. 修改python的环境变量PYTHONPATH,把cdctools.py的所在目录路径加入
    2. 在程序里动态的修改sys.path,如下所示:

   1 import sys
   2 # cdctools.py的路径添加到sys.path
   3 sys.path.append('/home/shengyan/workspace/obp/CDays/cdays2/')
   4 from cdctools import *
  • 经过本章Karrigell的初步学习,实现一个简易的web留言系统。主要利用Karrigell_quick_form实现提交留言并显示出来。
    1. 具体步骤:
      1. 下载karrigell,解压后,根据默认设置直接就可以运行了,但一般修改conf/下Karrigell.ini中的port=8081,表示使用端口8081,保存
      2. 将msg拷贝至webapps/,并在index.pih中增加链接<a href='msg/'> Message</a>

      3. 编辑msg中的index.ks,完成所需功能
      4. cd至karrigell所在目录,输入python Karrigell.py运行后,在浏览器地址栏中输入localhost:8081就可以看到页面,点击Message链接即可到达。

   1 # -*- coding: utf-8 -*-
   2 
   3 import os,sys
   4 import pickle          # 神奇的序列化模块
   5 from HTMLTags import * # Karrigell 提供页面输出支持模块
   6 from Karrigell_QuickForm import Karrigell_QuickForm as KQF
   7 
   8 def _htmhead(title):
   9     '''默认页面头声明
  10     @note: 为了复用,特别的组织成独立函式,根据Karrigell 非页面访问约定,函式名称前加"_"
  11     @param title: 页面标题信息
  12     @return: 标准的HTML代码
  13     '''
  14     htm = """<html><HEAD>
  15 <meta http-equiv="Content-Type" content="text/html;charset=utf-8"/>
  16 <title>%s</title></HEAD>
  17 <body>"""%title
  18     return htm
  19 ## 默认页面尾声明
  20 htmfoot="""
  21 <h5>design by:<a href="mailto:[email protected]">lizzie</a>
  22     powered by : <a href="http://python.org">Python</a> +
  23  <a href="http://karrigell.sourceforge.net"> KARRIGELL 2.4.0</a>
  24 </h5>
  25 </body></html>"""
  26 
  27 def index(**args):
  28     '''默认主
  29     @note: 使用简单的表单/链接操作来完成原有功能的界面化
  30     @param args: 数组化的不定参数
  31     @return: 标准的HTML页面
  32     '''
  33     print _htmhead("Leave Messages")
  34     p = KQF('fm_message','POST',"index","Message")
  35     p.addHtmNode('text','yname','Name',{'size':20,'maxlength':20})
  36     p.addTextArea('Words','10','90')
  37     p.addGroup(["submit","btn_submit","Submit","btn"])
  38     p.display()
  39     
  40     if 0 == len(QUERY):
  41         pass
  42     else:
  43         if "Submit" in QUERY['btn_submit']:
  44             yname = QUERY['yname']
  45             ywords = QUERY['Words']
  46             if 0 == len(ywords):
  47                 print H3("please say something!")
  48             else:
  49                 if 0 == len(yname):
  50                     yname = 'somebody'
  51                 try:
  52                     msg = pickle.load(open("message.dump"))
  53                 except:
  54                     msg = []
  55                 msg.append((yname, ywords))
  56                 index = len(msg)-1
  57                 while index >= 0:
  58                     print H5(msg[index][0]+' says: ')
  59                     print P('------ '+msg[index][1])
  60                     index -= 1
  61                 pickle.dump(msg,open("message.dump","w"))
  62         else:
  63             pass
  64     print htmfoot
  • 运行结果截图 attachment:cdays+2-exercise-2.png

1.1.9. CDays+3

  • 熟悉线程相关知识后,利用Lock和RLock实现线程间的简单同步,使得10个线程对同一共享变量进行递增操作,使用加锁机制保证变量结果的正确。

   1 #coding:utf-8
   2 '''cdays+3-exercise-1.py 使用Thread和RLock实现简单线程同步
   3 '''
   4 from threading import Thread
   5 from threading import RLock
   6 import time
   7 
   8 class myThread(Thread):
   9         '''myThread
  10                 自定义的线程,多个线程共同访问一个变量
  11         '''
  12         def __init__(self, threadname):
  13                 Thread.__init__(self, name = threadname)
  14 
  15         def run(self):
  16                 #共享一全局变量
  17                 global share_var
  18                 #调用lock的acquire,获得锁
  19                 lock.acquire()
  20                 #修改共享变量
  21                 share_var += 1
  22                 #time.sleep(2)
  23                 print share_var
  24                 #释放
  25                 lock.release()
  26         
  27 if __name__ == "__main__":
  28         share_var = 0
  29         lock = RLock()
  30         threadlist = []
  31         #产生10个线程
  32         for i in range(10):
  33                 my = myThread('Thread%d' % i)
  34                 threadlist.append(my)
  35         #开始10个线程
  36         for i in threadlist:
  37                 i.start()
  • 使用Queue实现多线程间的同步。比如说,十个输入线程从终端输入字符串,另十个输出线程依次获取字符串并输出到屏幕。

   1 #coding:utf-8
   2 '''cdays+3-exercise-2.py 使用Thread和Queue保持多线程间同步
   3 '''
   4 from threading import Thread
   5 import Queue
   6 import time
   7 
   8 class Input(Thread):
   9         '''输入线程: 从标准输入中读一个string,然后把该string加入到queue
  10         '''
  11         def __init__(self, threadname):
  12                 Thread.__init__(self, name = threadname)
  13         def run(self):
  14                 #输入一个字符串
  15                 some_string = raw_input('please input something for thread %s:' % self.getName())
  16                 global queue
  17                 #加入到队列
  18                 queue.put((self.getName(), some_string))
  19                 #延时一段时间
  20                 #time.sleep(5)
  21         
  22 class Output(Thread):
  23         '''输出线程:从queue中得到一个string,并将它输出到屏幕
  24         '''
  25         def __init__(self, threadname):
  26                 Thread.__init__(self, name = threadname)
  27         def run(self):
  28                 global queue
  29                 #从queue中读取
  30                 (iThread, something) = queue.get()
  31                 print 'Thread %s get "%s" from Thread %s' % (self.getName(), something, iThread)
  32 
  33 if __name__ == "__main__":
  34     #创建Queue对象
  35     queue = Queue.Queue()
  36     inputlist = []
  37     outputlist = []
  38     for i in range(10):
  39         #输入线程列表
  40         il = Input('InputThread%d' % i) 
  41         inputlist.append(il)
  42         #输出线程列表
  43         ol = Output('outputThread%d' % i)
  44         outputlist.append(ol)
  45     for i in inputlist:
  46         #依次开始输入线程
  47         i.start()
  48         #等待
  49         i.join()
  50     for i in outputlist:
  51         #依次开始输出线程
  52         i.start()
  53         #i.join()
  • Python中的Event是用于线程间的相互通信,主要利用信号量机制。修改题一的程序,利用信号量重新实现多线程对同一共享变量进行递增操作。

   1 #coding:utf-8
   2 '''cdays+3-exercise-3.py 使用Thread和Event实现简单的线程通信
   3 '''
   4 from threading import Thread
   5 from threading import Event
   6 import time
   7 
   8 class myThread(Thread):
   9         '''myThread
  10                 自定义线程
  11         '''
  12         def __init__(self, threadname):
  13                 Thread.__init__(self, name = threadname)
  14 
  15         def run(self):
  16                 global event
  17                 global share_var
  18                 #判断event的信号标志
  19                 if event.isSet():
  20                         #若设置了,则清除
  21                         event.clear()
  22                         #并调用wait方法
  23                         event.wait()
  24                         #time.sleep(2)
  25                         #修改共享变量
  26                         share_var += 1
  27                         print '%s ==> %d' % (self.getName(), share_var)
  28                 else:
  29                         #未设置,则直接修改
  30                         share_var += 1
  31                         print '%s ==> %d' % (self.getName(), share_var)
  32                         #time.sleep(1)
  33                         #设置信号标志
  34                         event.set()
  35         
  36 if __name__ == "__main__":
  37         share_var = 0
  38         #创建Event对象
  39         event = Event()
  40         #设置内部信号标志为真
  41         event.set()
  42         threadlist = []
  43         #创建10个线程
  44         for i in range(10):
  45                 my = myThread('Thread%d' % i)
  46                 threadlist.append(my)
  47         #开启10个线程
  48         for i in threadlist:
  49                 i.start()
  • 运行结果截图 attachment:cdays+3-exercise-12.png attachment:cdays+3-exercise-3.png

1.2. KDays

1.3. 小结


ObpLovelyPython/LpyAttach3answer (last edited 2009-12-25 07:14:24 by localhost)