PYTHON多线程处理文件

一个几十G的文件想用Python多线程读取提高处理效率,得到的结果总是不如预期。在毛帅的提醒下才发现一个进程启动的线程将共享文件句柄,A线程对文件的操作(即使是读)也将影响到B线程。如图,图片来自毛帅:

测试代码如下:

# -*- coding: UTF-8 -*-

def threadFunc1(demo, threadnum, startlinenum, deallinenum):
    # 行数计数器
    line = 0
    # skip若干行
    while line < startlinenum:
        lineStr = demo.readline()
        line += 1
    # deal指定行数
    while line < deallinenum:
        lineStr = demo.readline()
        line += 1
        print "Thread-%s:%s" % (threadnum, lineStr)

def threadFunc2(demo, threadnum, startlinenum, deallinenum):
    linenum = 1
    for line in demo:
        if linenum >= startlinenum and linenum < (startlinenum+deallinenum):
            print "Thread-%s:%s" % (threadnum, line)
        elif (linenum >= (startlinenum+deallinenum)):
            break;
        linenum = linenum+1

import threading

if __name__ == "__main__":
    # 初始化demo文件
    fileLoc = ‘demo.txt‘
    demo = open(fileLoc,‘w‘)
    for i in range(100000):
            demo.write("Line:"+str(i)+‘\n‘)
    demo.close()

    # 预读文件总行数
    demo = open(fileLoc,‘r‘)
    filetotalnum = 0
    for line in demo:
            filetotalnum = filetotalnum + 1
    demo.close()

    # 设定线程数
    TOTAL_THREAD = 6
    # 在主进程总打开文件,将文件句柄传至线程启动的函数中
    demo = open(fileLoc,‘r‘)
    for threadnum in range(TOTAL_THREAD):
        # 每个线程处理的行数
        deallinenum = filetotalnum / (TOTAL_THREAD-1)
        # 最后一个线程处理剩余部分
        leftnum = filetotalnum % (TOTAL_THREAD-1)
        if(threadnum != (TOTAL_THREAD-1)):
            # 实例化线程
            t = threading.Thread(target=threadFunc2,args=(demo, threadnum, threadnum*deallinenum, threadnum*deallinenum+deallinenum))
            # 启动
            t.start()
            # 等待线程结束后主进程退出
            t.join()
        else :
            t = threading.Thread(target=threadFunc2,args=(demo, threadnum, threadnum*deallinenum, threadnum*deallinenum+leftnum))
            t.start()
            t.join()

threadFunc2函数中利用句柄参数读取文件,但结果是有些线程有正常输出,其它一些线程则无输出。目测原因是线程切换的随机性影响了本来应正常进行读取的线程(例如一些线程正好定位到属于其处理范围的行时发生线程切换,而其它线程获得时间片后在这个位置基础上继续处理)。

threadFunc1使用readLine进行读取,但本质同threadFunc2一样。

如果传给threadFuncx的并不是在主线程中打开的文件句柄而是一个文件路径,并在threadFuncx内部打开文件,结果表现为各个线程都有输出,但是输出的内容并非分配给其的文件片段的内容,有干涉。

细节上未进行深入研究,总之不加锁的情况下,python启动多线程读取文件会得到非预期结果。

至于最后的解决方案,是利用awk对文件进行“模数切割”,Mod的不同余数分别对应一个处理线程。

targetFile=xxx
threadNum=5    # 设定五个线程
for((i=0; i<threadNum; i++))
do
    awk ‘NR%n==t {print $0}‘ n=$threadNum t=$i $targetFile | python doTask.py &
done
时间: 2024-08-03 16:12:45

PYTHON多线程处理文件的相关文章

Python读写文件

Python读写文件1.open使用open打开文件后一定要记得调用文件对象的close()方法.比如可以用try/finally语句来确保最后能关闭文件. file_object = open('thefile.txt')try:     all_the_text = file_object.read( )finally:     file_object.close( ) 注:不能把open语句放在try块里,因为当打开文件出现异常时,文件对象file_object无法执行close()方法.

解决Python读取文件时出现UnicodeDecodeError: &#39;gbk&#39; codec can&#39;t decode byte...

用Python在读取某个html文件时会遇到下面问题: 出问题的代码: 1 if __name__ == '__main__': 2 fileHandler = open('../report.html', mode='r') 3 4 report_lines = fileHandler.readlines() 5 for line in report_lines: 6 print(line.rstrip()) 修改方式是在open方法指定参数encoding='UTF-8': if __nam

将Python脚本文件包装成可执行文件

将Python脚本文件包装成可执行文件,其目的有二: 一则: 不需要依赖Python编译器就可以运行软件 二则: 不想让自己的源码公布出去 常用的工具有: py2exe.cx_freeze等 [工具:py2exe] 安装py2exe 安装该工具很简单: 只需要从官方网站:http://www.py2exe.org/下载与版本对应的安装程序,点击下一步即可完成安装. 安装后,执行import py2exe,不报错则表示安装成功! >>> import py2exe >>>

[改]在windows右键菜单中加入“新建Python File文件”并创建模板

1.首先写好模板文件,随便保存在一个地方,比如我是"D:\Python27\foo.py"; 2.打开注册表(regedit),找到 [HKEY_CLASSES_ROOT] -> [.py] (没有的话,自己新建项.py); 3.在 [.py] 下新建项 [ShellNew] (已经有的话就删掉重建); 4.在 [ShellNew] 下新建 字符串值 ,名称为 FileName ,键值为模板文件的绝对路径,比如我的是 D:\Python27\foo.py ; 在右键新建菜单中就会

python之文件对象

防伪码忘情公子著 文件对象是用来访问文件系统接口所对应的数据的 文件系统是OS用于明确磁盘或分区上的文件的方法和数据结构-即在磁盘上组织文件的方法 计算机文件或称文件.电脑档案.档案是存储在某种长期储存设备或临时存储设备中的一段数据流并且归属于计算机文件系统管理之下 概括来讲 文件是计算机中由OS管理的具有名字的存储区域 在Linux系统上文件被看做是字节序列 要想把数据存储到文件中有一个前提那就是必须序列化非序列化的数据是不能简单的存储在文件系统中的文件中的 对于python来说文件对象不仅可

Python open文件读写模式说明

对于Python打开文件的模式,总是记不住,这次在博客里记录一下 r+: Open for reading and writing.  The stream is positioned  at  the beginning of the file. w+:Open for reading and writing.  The file is created  if  it  does not  exist, otherwise it is truncated.  The stream is pos

从自动生成.h的头文件集合和类声明集合到用python读写文件

最近在用python自动生成c++的类.因为这些类会根据需求不同产生不同的类,所以需要用python自动生成.由于会产生大量的类,而且这些类是变化的.所以如果是在某个.h中要用include来加载这些类,会累死人的.所以用python来生成这些类的头文件引用和类的类名声明 先看例子,再聊python的读写文件的代码 在聊聊我的python代码 ------------------------> 好吧.上面的图就是面临的需求 下面来聊聊从网上找的读写文件的python代码吧.csdn的一个博主写的

python之文件操作-复制、剪切、删除等

下面是把sourceDir文件夹下的以.JPG结尾的文件全部复制到targetDir文件夹下: <span style="font-size:18px;">>>>import os >>> import os.path >>> import shutil >>> def copyFiles(sourceDir,targetDir): for files in os.listdir(sourceDir):

Python Selenium 文件上传(二)

今天补充一种文件上传的方法 主要是因为工作中使用SendKeys方法不稳定,具体方法见: Python Selenium 文件上传(一) 这种方法直接通过命令行执行脚本时没有问题,可以成功上传,但是如果通过saltstack 远程控制执行时,SendKeys就定位不到窗口了. 所以采用这种新的方式来实现文件上传功能,并完美的解决了这个问题. 具体操作步骤如下: 1.下载工具 AutoIt及使用 AutoIt目前最新是v3版本,这是一个使用类似BASIC脚本语言的免费软件,它设计用于Windows