python面试--多进程分块处理大型文件

# -*- 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后也不会有影响,因为是循环起的进程。

你可能感兴趣的:(python面试编程题)