# -*- coding: utf8 -*-
import datetime
from multiprocessing import Process, Manager, RLock
from itertools import islice
"""
多进程分块读取文件
"""
class File_Manager(object):
def func_countfileline(self, filepath):
"""
计算文件的总行数
:param filepath: 文件
:return:int,文件总行数
"""
num =1
thefile=open(filepath, 'rb')
while True:
buffer = thefile.read(102400)
if not buffer:
break
num += buffer.count('\n')
thefile.close()
return num
def process_found_new(self, FILE_COUNT, pid, result, file, rlock):
"""
对文件内容进行统计,每次读取最多2000行
:param FILE_COUNT: 文件读取的起始行
:param pid: 进程id
:param result: dict格式,处理的结果
:param file: 文件
:param rlock: 锁
:return:
"""
# import os
# print os.getpid()
global BLOCKLINE
with open(file, 'rb') as fstream:
rlock.acquire()
print 'pid%s'% pid
count = 0
for line in islice(fstream, FILE_COUNT, None):
if count < BLOCKLINE:
func_name = line.split(' ')[2]
if result.get(func_name):
result[func_name] += 1
else:
result[func_name] = 1
count += 1
else:
break
rlock.release()
print 'pid%s end!'% pid
def main(self, file):
"""
根据文件总行数,每次处理2000行, 判断起几个进程,然后每个进程对文件进行处理
:param file: 文件
:return: result,最终对文件的统计结果
"""
BLOCKLINE = 10000
global BLOCKLINE
print datetime.datetime.now().strftime("%Y/%d/%m %H:%M:%S")
count = self.func_countfileline(file)
WORKERS = count/BLOCKLINE + 1 if count % BLOCKLINE else count/BLOCKLINE
rlock = RLock()
manager = Manager()
result = manager.dict()
processes = []
for i in range(WORKERS):
p=Process(target=self.process_found_new, args=[i*BLOCKLINE, i, result, file, rlock])
p.daemon = True
processes.append(p)
for i in range(WORKERS):
processes[i].start()
for i in range(WORKERS):
processes[i].join()
print result
print datetime.datetime.now().strftime("%Y/%d/%m %H:%M:%S")
if __name__ == '__main__':
file = "D:\\webcgi.std"
file_manager = File_Manager()
file_manager.main(file)
备注下:
主函数中,调用进程调用了start后,又继续遍历调用了join,原因如下:
start:若Process不指定target,就会直接调用Process默认的run()方法。
join:是主进程等待join的进程结束后,再继续执行。也就是如果不加join,main函数不会等待进程继续,而是直接继续执行。
那为什么不是start一个进程就加一个join?
这是因为若起了进程1,然后就加了个join,那么进程1结束后,main函数就会继续运行。并不会等其他进程结束。
当然这个代码中,join加到start后也不会有影响,因为是循环起的进程。