python多线程读取文件的问题

本地文件内容为每行一个url

python代码如下:

#!/usr/bin/env python
# coding=utf8

import requests
import threadpool as tp

num = 200 
urllist = open('./url.txt', 'r')

def start(args):
    flag = 0 
    for url in urllist.readlines():
        url = url.strip('\n')
        try:
            res = requests.get(url)
        except:
            print "[ERROR] [%s] %s\n" % (flag, url)
            continue

        flag += 1
        print "[%s] %s : %s\n" % (flag, url, res.status_code)

args = range(0, num)

pool = tp.ThreadPool(num)
reqs = tp.makeRequests(start, args)
[pool.putRequest(req) for req in reqs]
pool.wait()
pool.dismissWorkers(num, do_join=True)
print "Done.\n"

由于文件较大(200M左右),检查执行日志发现有时候进程读取到的每行内容不全。
有时候只读取到"http://xxx.com/",后面的部分就没有了,导致请求出错。

求大神指导。

阅读 8.7k
2 个回答

这是一个很明显的多线程竞争问题。看了问题描述,感觉在多线程下处理起来很麻烦。
如果可以的话,建议用单线程解决最好。在我的电脑上,200M的文件,瞬间就读完了,没有延迟。
如果一定要用多线程,请追问(强烈不建议多线程解法)。

但线程中readlines()就已经全部读完文件了,
多线程共同调用同一个文件对象的io方法会造成偏移量错误的问题,你需要锁。(python3 有 os.pread 函数,这个是原子操作,可以不用锁)。
这个问题使用线程的效率价值在requests处,200M的文件读取还轮不到谈文件读取的多线程加速。实际上因为GIL,在python的多线程中你也无法提高IO速度。

import requests
import multiprocessing
import sys

urlfile = 'url.txt'

def gen_urls(filename):
    with open(filename, 'r') as f:
        l = f.readline()
        while l:
            l = l.strip('\n')
            yield l
            l = f.readline()

def check_url(url):
    res = requests.get(url)
    print("{s}: {u}".format(s=res.status_code, u=url))

def run_in_pool():
    pool = multiprocessing.Pool(processes=8)
    for url in gen_urls(urlfile):
        print("To pool: {}".format(url))
        pool.apply_async(check_url, (url,))
    pool.close()
    pool.join()
    print("done")

def run_in_one():
    for url in gen_urls(urlfile):
        print("To pool: {}".format(url))
        check_url(url)
    print("done")

if __name__ == "__main__":
    if sys.argv.pop() == "m":
        run_in_pool()
    else:
        run_in_one()
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题