文档章节

PYTHON多线程处理文件

Iuranus
 Iuranus
发布于 2014/10/13 20:18
字数 748
阅读 8194
收藏 14

一个几十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


如果文章对你有用,请在收藏之余“顶/赞”一下以示鼓励吧 (/ω\)

© 著作权归作者所有

Iuranus
粉丝 12
博文 41
码字总数 22439
作品 0
高级程序员
私信 提问
1. 文本处理加速(利用多核优势进行文本的并列处理)

人生苦短,我用Python!然后学学使用Shell。 任务要求 在写爬虫或是做文本数据清洗的时候,有的时候发现我们用python写的处理程序会遇到速度过慢的问题,造成这个的原因可能如下: Python 自...

北静王
2018/08/13
0
0
酷! 给python脚本配一个动画界面

python黑乎乎的命令行输出太乏味了。本篇用pyui4win开发一个有动画界面的python执行程序。 当用户选择执行时,动画开启,开始转圈,直到python功能函数执行完成。在执行过程中,界面上的信息...

编码的风景
2013/08/26
0
0
python标准库00 学习准备

Python标准库----走马观花 python有一套很有用的标准库。标准库会随着python解释器一起安装在你的电脑上的.它是python的一个组成部分.这些标准库是python为你准备的利器,可以让编程事半功倍....

肖邦0526
2015/12/29
0
0
买《Python从小白到大牛》专题视频课程,送配套纸质图书

经过一年多时间的呕心沥血,Python立体化图书——《Python从小白到大牛》即将与大家见面了。所谓立体化图书包括:电子图书、视频、课件和服务等内容。 《Python从小白到大牛》纸质图书将于9...

tony关东升
2018/07/23
0
0
一篇文章搞定Python多进程(全)

公众号:pythonislover 前面写了三篇关于python多线程的文章,大概概况了多线程使用中的方法,文章链接如下: 一篇文章搞懂Python多线程简单实现和GIL - https://mp.weixin.qq.com/s/Hgp-x-...

南山yrg
05/05
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Redux

Redux概念 Redux = Reducer + Flux,数据层框架,将所有数据都存储到store中 Redux的工作流程 Antd的使用 安装npm install antd --save import 'antd/dist/antd.css'import { Input, Butto......

星闪海洋
今天
4
0
OSChina 周一乱弹 —— 你们谁看见了我的诺贝尔奖

Osc乱弹歌单(2019)请戳(这里) 【今日歌曲】 @脚板薯 :这么晚不睡只为找到一首歌,晚安。 ♫Say You Want Me♪ ♫Say You Want Me♪ - Augustana 手机党少年们想听歌,请使劲儿戳(这里)...

小小编辑
今天
368
17
我为什么要写微信公众号

埋一颗种子,细心呵护,静待她枝繁叶茂,葱郁参天 V2论坛上有个帖子【做程序员最重要的还是一定要有自己的作品】,作者写道: 能有一个作品和你的名字联系在一起,应当成为在职业生涯前期着意...

运维咖啡吧
今天
3
0
数据库

数据库架构 数据库架构可以分为存储文件系统和程序实例两大块,而程序实例根据不同的功能又可以分为如下小模块。 1550644570798 索引模块 常见的问题有: 为什么要使用索引 什么样的信息能成...

一只小青蛙
今天
5
0
PHP常用经典算法实现

<? //-------------------- // 基本数据结构算法 //-------------------- //二分查找(数组里查找某个元素) function bin_sch($array, $low, $high, $k){ if ( $low <= $high){ $mid = int......

半缘修道半缘君丶
昨天
6
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部