使用线程/多进程读取多个文件

时间:2015-08-11 06:08:36

标签: python multithreading multiprocessing

我目前正在从FileNameList的路径列表中提取.txt文件,这是有效的。但我的主要问题是,当文件太多时,它太慢了。

我正在使用此代码打印txt文件列表

import os
import sys

#FileNameList is my set of files from my path
for filefolder in FileNameList: 
  for file in os.listdir(filefolder): 
    if "txt" in file:
        filename = filefolder + "\\" + file     
        print filename

任何有线程/多进程并使其快速阅读的帮助或建议都会接受。提前谢谢。

4 个答案:

答案 0 :(得分:3)

多线程或多处理不会加快速度;你的瓶颈是存储设备。

答案 1 :(得分:3)

  

所以你的意思是没有办法加速这个?,因为我的方案是读取一堆文件然后读取它的每一行并将其存储到数据库

优化的第一条规则就是问问自己是否应该打扰。如果您的程序只运行一次或几次优化它是浪费时间。

第二条规则是在您执行任何其他操作之前,衡量问题所在;

编写一个简单的程序,按顺序读取文件,将它们分成行并填充数据库中的文件。 在 profiler 下运行该程序,以查看程序在大部分时间内花费的时间。

只有这样你才知道程序的哪一部分需要加速。

不过,这里有一些指示。

  • 使用mmap
  • 可以完成文件阅读
  • 您可以使用multiprocessing.Pool分散在不同核心上读取多个文件。但是那些来自这些文件的数据将最终进入不同的进程,并且必须使用IPC将其发送回父进程。这对于大量数据来说有很大的开销。
  • 在Python的CPython实现中,一次只有一个线程可以执行Python字节码。虽然文件的实际读数没有被禁止,但处理结果是。因此,线程是否会提供改进是值得怀疑的。
  • 将这些行填充到数据库中可能永远是一个主要的瓶颈,因为这是所有东西汇集在一起​​的地方。这有多大问题取决于数据库。它是在内存中还是在磁盘上,它是否允许多个程序同时更新它,等等。

答案 2 :(得分:2)

根据文件的数量和大小,您可以获得一些加速。查看类似问题的答案:Efficient file reading in python with need to split on '\n'

基本上,您可以使用多线程,多处理或其他方式(例如迭代器)并行读取多个文件...并且可能获得一些加速。最简单的方法是使用像pathos这样的库(是的,我是作者),它在一个通用API中提供多处理,多线程和其他选项 - 基本上,你可以编码它一次,然后在不同的后端之间切换,直到你的情况最快。

不同类型的地图有很多选项(在pool对象上),您可以在此处看到:Python multiprocessing - tracking the process of pool.map operation

虽然以下不是最具想象力的示例,但它显示了一个双嵌套映射(相当于一个双嵌套的for循环),以及更改后端及其他选项的容易程度。

>>> import pathos
>>> p = pathos.pools.ProcessPool()
>>> t = pathos.pools.ThreadPool()
>>> s = pathos.pools.SerialPool()
>>> 
>>> f = lambda x,y: x+y
>>> # two blocking maps, threads and processes
>>> t.map(p.map, [f]*5, [range(i,i+5) for i in range(5)], [range(i,i+5) for i in range(5)])
[[0, 2, 4, 6, 8], [2, 4, 6, 8, 10], [4, 6, 8, 10, 12], [6, 8, 10, 12, 14], [8, 10, 12, 14, 16]]
>>> # two blocking maps, threads and serial (i.e. python's map)
>>> t.map(s.map, [f]*5, [range(i,i+5) for i in range(5)], [range(i,i+5) for i in range(5)])
[[0, 2, 4, 6, 8], [2, 4, 6, 8, 10], [4, 6, 8, 10, 12], [6, 8, 10, 12, 14], [8, 10, 12, 14, 16]]
>>> # an unordered iterative and a blocking map, threads and serial
>>> t.uimap(s.map, [f]*5, [range(i,i+5) for i in range(5)], [range(i,i+5) for i in range(5)])
<multiprocess.pool.IMapUnorderedIterator object at 0x103dcaf50>
>>> list(_)
[[0, 2, 4, 6, 8], [2, 4, 6, 8, 10], [4, 6, 8, 10, 12], [6, 8, 10, 12, 14], [8, 10, 12, 14, 16]]
>>> 

我发现通常情况下,无序迭代映射(uimap)是最快的,但是你不必关心处理哪个顺序,因为它可能在返回时失序。至于速度...通过调用time.time或类似的方式围绕上面。

在此处获取pathoshttps://github.com/uqfoundation

答案 3 :(得分:0)

在这种情况下,您可以尝试使用多线程。但请记住,由于Python GIL(全局解释器锁定),每个非原子操作都将在单个线程中运行。如果您正在运行多台计算机,则可能会更快。你可以使用类似工人生产者的东西:

  • Producer(一个线程)将保存文件列表和队列
  • Worker(多个线程)将从队列中收集文件信息并将内容推送到数据库

查看多处理(实际分离的子进程)中的队列和管道以回避GIL。

使用这两个通信对象,您可以构建一些很好的阻塞或非阻塞程序。

附注:请记住,并非每个数据库连接都是线程安全的。