WEB开发网
开发学院软件开发Python 如何编写Unix管道风格的Python代码 阅读

如何编写Unix管道风格的Python代码

 2010-09-22 11:10:40 来源:WEB开发网   
核心提示: 然而,设想以后有了新的统计任务,如何编写Unix管道风格的Python代码(2),比如:1.统计某个特定页面的访问次数2.处理另外的一些日志文件,日志文件名字以 error-log 开头完成这些任务直接拿上面的代码过来改改就可以了,因此在其他任务中很可能就无法使用,另外 add_count

然而,设想以后有了新的统计任务,比如:

1.统计某个特定页面的访问次数

2.处理另外的一些日志文件,日志文件名字以 error-log 开头

完成这些任务直接拿上面的代码过来改改就可以了,文件名的 pattern 改一下,处理每个文件的代码改一下。其实每次任务的处理中,找到特定名字为特定 pattern 的文件的代码是一样的,直接修改之前的代码其实就引入了重复。

如果重复的代码量很大,我们很自然的会注意到。然而 python 的 for 循环实在太方便了,像这里找文件的代码一共就两行,哪怕重写一遍也不会觉得太麻烦。for 循环的方便使得我们会忽略这样简单代码的重复。然而,再怎么方便好用,for 循环无法重用,只有把它放到函数中才能进行重用。

(先考虑下是你会如何避免这里的代码的重复。下面马上出现的代码并不好,是“误导性”的代码,我会在之后再给出“更好”的代码。)

因此,我们把上面代码中不变的部分提取成一个通用的函数,可变的部分以参数的形式传入,得到下面的代码:

def generic_process(topdir, filepat, processfunc):
  for path, dirlist, filelist in os.walk(top):
    for name in fnmatch.filter(filelist, filepat):
      with open(name) f:
        processfunc(f)
sum = 0
# 很遗憾,python 对 closure 中的变量不能进行赋值操作,
# 因此这里只能使用全局变量
def add_count(f):
  global sum
  for line in f:
    if line[-1] == '-':
      continue
    else:
      sum += int(line.rsplit(None, 1)[1])
generic_process('logdir', 'access-log*', add_count)

看起来不变和可变的部分分开了,然而 generic_process 的设计并不好。它除了寻找文件以外还调用了日志文件处理函数,因此在其他任务中很可能就无法使用。另外 add_count 的参数必须是 file like object,因此测试时不能简单的直接使用字符串。

Tags:如何 编写 Unix

编辑录入:爽爽 [复制链接] [打 印]
赞助商链接