python多线程处理文件安全_Python多线程文件处理

你混淆了两种不同的解决方案。

如果要为每个文件创建专用的工作线程,则不需要队列。如果要创建一个线程池和一个文件队列,则不希望将inpfile和outfile传递给run方法;而是希望将它们放入队列中的每个作业中。

你如何在两者之间做出选择?好吧,第一个显然更简单,但是如果你有,比如说,1000个文件要复制,你最终会创建1000个线程,这比你想创建的线程要多,而且线程数量远远超过操作系统能够处理的并行副本的数量。一个线程池允许您创建,比如说,8个线程,并将1000个作业放在一个队列中,它们将根据需要分发给线程,因此一次运行8个作业。

让我们从解决方案1开始,每个文件都有一个专用的工作线程。

首先,如果你没有与子类Thread结婚,那么这里真的没有理由这么做。您可以将一个target函数和一个args元组传递给默认构造函数,然后run方法将只做target(*args),完全按照您的需要。所以:t = threading.Thread(target=workermethod, args=(inpfile, outfile))

这就是你所需要的。当每个线程运行时,它将调用workermethod(inpfile, outfile),然后退出。

但是,如果出于某种原因,您确实想对Thread进行子类划分,那么您可以。您可以在构造时传入inpfile和outfile,而您的run方法只需将workermethod修改为使用self.inpfile和self.outfile而不是使用参数。像这样:class ThreadUrl(threading.Thread):

def __init__(self, inpfile, outfile):

threading.Thread.__init__(self)

self.inpfile, self.outfile = inpfile, outfile

def run(self):

f1 = open(self.inpfile,'r')

f2 = open(self.outfile,'w')

x = f1.readlines()

for each in x:

f2.write(each)

f1.close()

f2.close()

不管怎样,我建议使用with语句,而不是显式的open和close,并去掉readlines(不必要地将整个文件读入内存),除非您需要处理Python的旧版本:def run(self):

with open(self.inpfile,'r') as f1, open(self.outfile,'w') as f2:

for line in f1:

f2.write(line)

现在,转到解决方案2:线程池和队列。

同样,这里不需要子类;这两种方法之间的区别与解决方案1中的相同。但是坚持你已经开始的子类设计,你需要这样的东西:class ThreadUrl(threading.Thread):

def __init__(self,queue):

threading.Thread.__init__(self)

self.queue = queue

def run(self):

while True:

inpfile, outfile = self.queue.get()

workermethod(inpfile, outfile)

然后通过向所有线程传递一个queue来启动线程:q = queue.Queue

threadpool = [ThreadUrl(q) for i in range(poolsize)]

提交如下作业:q.put((inpfile, outfile))

如果您打算认真对待线程池,那么您可能需要考虑使用健壮、灵活、简单和优化的实现,而不是自己编写代码。例如,您可能希望能够取消作业、很好地关闭队列、连接整个池而不是逐个连接线程、执行批处理或智能负载平衡等

如果您使用的是Python 3,那么应该查看标准库ThreadPoolExecutor。如果您被Python 2困住了,或者无法找出Futures,那么您可能需要查看隐藏在multiprocessing模块中的ThreadPool类。这两种方法都有一个优点,那就是从多线程转换到多处理(如果,比方说,你有一些需要与IO并行的CPU相关的工作)是微不足道的。您还可以search PyPI找到多个其他好的实现。

顺便说一下,您不想调用队列queue,因为这将隐藏模块名。另外,有一个叫做workermethod的东西实际上是一个自由函数而不是一个方法,这有点让人困惑。

最后,如果你所做的只是复制文件,你可能不想在文本模式下阅读,或者逐行阅读。实际上,您可能根本不想自己实现它;只需使用shutil中的适当复制函数。你可以用上述任何一种方法很容易做到这一点。例如,与此相反:t = threading.Thread(target=workermethod, args=(inpfile, outfile))

执行以下操作:t = threading.Thread(target=shutil.copyfile, args=(inpfile, outfile))

事实上,你的整个程序看起来可以替换为:threads = [threading.Thread(target=shutil.copyfile, args=(inpfile, outfile))

for (inpfile, outfile) in zip(filelistread, filelistwrte)]

for thread in threads:

thread.start()

for thread in threads:

thread.join()

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值