Python 使用不同线程读取文件

Python 使用不同线程读取文件,python,multithreading,Python,Multithreading,我正在尝试使用Python读取和修改许多文件的每一行。每个文件都有数千到数十万行,因此,如果处理了每个文件,则只能在处理另一个文件之后再处理。我试图读取如下文件: csvReader = csv.reader(open("file","r") for row in csvReader: handleRow(row) 我想使用多线程来读取使用不同线程并行的每个文件,以节省时间。有人能指出它是否有用以及如何实现它吗?它可能有用,也可能无用——如果所有文件都在同一个驱动器上,并且您已经在尽可

我正在尝试使用Python读取和修改许多文件的每一行。每个文件都有数千到数十万行,因此,如果处理了每个文件,则只能在处理另一个文件之后再处理。我试图读取如下文件:

csvReader = csv.reader(open("file","r")
for row in csvReader:
    handleRow(row)

我想使用多线程来读取使用不同线程并行的每个文件,以节省时间。有人能指出它是否有用以及如何实现它吗?

它可能有用,也可能无用——如果所有文件都在同一个驱动器上,并且您已经在尽可能快地推送驱动器,那么多路复用只会减慢速度。但是如果你没有最大化你的I/O,它会加快速度

至于怎么做,那是微不足道的。将代码封装在一个采用路径名的函数中,然后使用concurrent.futures.ThreadPoolExecutor或multiprocessing.dummy.Pool,这是一行代码,用于将函数映射到整个路径名:

with ThreadPoolExecutor(4) as executor:
    executor.map(func, paths)

还有一件事:如果你不能最大化I/O的原因是因为你在每一行上都做了太多的CPU工作,那么线程在Python中是没有帮助的(因为GIL),但是你可以只使用进程——完全相同的代码,但是使用ProcessorPoolExecutor。

如果所有文件都在同一个驱动器上,它可能有用,也可能无用,而且您已经在尽可能快地推动驱动器,多路复用只能降低速度。但是如果你没有最大化你的I/O,它会加快速度

至于怎么做,那是微不足道的。将代码封装在一个采用路径名的函数中,然后使用concurrent.futures.ThreadPoolExecutor或multiprocessing.dummy.Pool,这是一行代码,用于将函数映射到整个路径名:

with ThreadPoolExecutor(4) as executor:
    executor.map(func, paths)

还有一件事:如果你不能最大化I/O的原因是因为你在每一行上都做了太多的CPU工作,线程在Python中不会有帮助(因为GIL),但是你可以只使用进程——完全相同的代码,但是使用ProcessorPoolExecutor。

可能你的瓶颈是I/O,所以多线程没有帮助;无论如何,很容易尝试:下面的代码详细说明了当前目录中的所有文件,一个线程对应一个文件,方法是对每一行应用给定的字符串函数,并在给定的路径上写入新文件

from threading import Thread
from os import listdir
from os.path import basename, join, isfile

class FileChanger(Thread):
     def __init__(self, sourcefilename, rowfunc, tgpath):
         Thread.__init__(self)
         self.rowfunc = rowfunc
         self.sfname = sourcefilename
         self.tgpath = tgpath

     def run(self):
         tgf = open(join(self.tgpath, basename(self.sfname)), 'w')
         for r in open(self.sfname):
             tgf.write(self.rowfunc(r))
         tgf.close()

# main #
workers = [FileChanger(f, str.upper, '/tmp/tg') \
                for f in listdir('.') if isfile(f)]
for w in workers:
    w.start()
for w in workers:
    w.join()

可能您的瓶颈是I/O,因此多线程处理没有帮助;无论如何,很容易尝试:下面的代码详细说明了当前目录中的所有文件,一个线程对应一个文件,方法是对每一行应用给定的字符串函数,并在给定的路径上写入新文件

from threading import Thread
from os import listdir
from os.path import basename, join, isfile

class FileChanger(Thread):
     def __init__(self, sourcefilename, rowfunc, tgpath):
         Thread.__init__(self)
         self.rowfunc = rowfunc
         self.sfname = sourcefilename
         self.tgpath = tgpath

     def run(self):
         tgf = open(join(self.tgpath, basename(self.sfname)), 'w')
         for r in open(self.sfname):
             tgf.write(self.rowfunc(r))
         tgf.close()

# main #
workers = [FileChanger(f, str.upper, '/tmp/tg') \
                for f in listdir('.') if isfile(f)]
for w in workers:
    w.start()
for w in workers:
    w.join()

附带说明:您没有在任何地方关闭文件,如果您打开数百个文件,这将是一个严重的问题。附带说明:您没有在任何地方关闭文件,如果要打开数百个文件,这将是一个严重的问题。关于CPU和线程:的确,CPython不能对线程使用多处理器功能,这会导致GIL,但是如果您不想为整个进程付出代价,您仍然可以在没有GIL的Python实现上尝试您的代码,比如,除非他只有少数几个文件,否则每个线程使用一个文件可能会花费比节省更多的成本。应该只需要一小部分线程就可以获得任何可能带来的好处。@abarnert你说得对,上面只是一个例子。无论如何,为了使用“worker”列表作为具有上限大小的队列,对代码进行改进是很容易的:每次我们加入一个线程时,我们都会创建并启动另一个线程…@dbra 2个问题。1)为什么要使用w.join 2)线程完成后会自动结束吗?#我假设所有工作完成后,程序会执行其他操作,至少告诉某人;当然,你不能等着让他们一个人呆着;#创建一个线程并没有那么重,只是ms的问题,所以我发现cleaner定义了一个简单的一次性对象(比如Go的goroutines),将分发逻辑留在了外部;这也使得协调变得微不足道。关于CPU和线程:的确,CPython不能对线程使用多处理器功能,因为它会导致GIL,但是如果你不想为整个进程付出代价,你仍然可以在没有GIL的Python实现上尝试你的代码,比如。除非他只有少量文件,每个线程使用一个文件可能会花费比节省更多的成本。应该只需要一小部分线程就可以获得任何可能带来的好处。@abarnert你说得对,上面只是一个例子。无论如何,为了使用“worker”列表作为具有上限大小的队列,对代码进行改进是很容易的:每次我们加入一个线程时,我们都会创建并启动另一个线程…@dbra 2个问题。1)为什么要使用w.join 2)线程完成后会自动结束吗?#我假设所有工作完成后,程序会执行其他操作,至少告诉某人;当然,你不能等着让他们一个人呆着;#创建一个线程并没有那么重,只是ms的问题,所以我发现cleaner定义了一个简单的一次性对象(比如Go的goroutines),将分发逻辑留在了外部;这也使得协调变得微不足道。