【问题标题】:Multiple threads reading from single folder on Linux多个线程从 Linux 上的单个文件夹读取
【发布时间】:2011-12-09 08:00:17
【问题描述】:

我的项目需要多个线程从同一个文件夹中读取文件。该文件夹有传入文件,该文件只能由这些线程中的任何一个线程处理。稍后,这个文件读取线程,处理完文件后将其删除。

在第一个答案后编辑:我不想要一个线程负责读取文件名并将这些名称提供给其他线程,以便他们可以读取它。

在 python 中是否有任何有效的方法来实现这一点?

【问题讨论】:

  • 为什么不想使用单个线程将输入文件名传递给其他线程?
  • 如果我这样做,这个输入读取线程需要充当调度程序,将文件名提供给空闲线程。相反,如果有什么我已经可以使用的东西可以帮助我实现这一目标,那就太好了。
  • @Sujit 你不会找到不依赖工作队列模型的东西。你为什么不想使用它?我可以向你保证,这不会是瓶颈——磁盘访问会。
  • @Sujit:你可以组织你的代码,输入线程只调用queue.put(filename),而不是一个新的文件名可用(pyinotify 可能在这里有所帮助)。工作线程只是循环调用queue.get(filename)。输入线程对工作线程一无所知,反之亦然。

标签: python linux multithreading


【解决方案1】:

您可能应该使用Queue module。来自文档:

Queue 模块实现了多生产者、多消费者队列。当信息必须在多个线程之间安全地交换时,它在线程编程中特别有用。

我会使用 FIFO 方法,由一个线程负责检查入站文件并对其进行排队,并由多个工作人员处理它们。该模块还支持 LIFO 方法或使用自定义方法分配优先级的方法。


编辑:如果您不想使用Queue 模块并且您在*nix 系统下,您可以改用fcntl.lockf。另一种方法是使用os.open('filename', os.O_EXLOCK) 打开文件。

根据您执行此操作的频率,您可能会发现它的性能不如使用 Queue,因为您必须考虑竞争条件(即:您可能会获取要打开的文件的名称,但文件在你有机会打开它之前可能会被另一个线程锁定,抛出一个你必须捕获的异常)。 Queue 是有原因的! ;)


EDIT2: 在这个问题和其他问题中的评论提出了同时访问不同文件的磁盘问题以及随之而来的性能损失。我在想task_done 本来可以用来防止这种情况发生,但是在阅读其他人的 cmets 时,我突然想到,与其对文件名进行排队,不如直接对文件的内容进行排队。考虑到 RAM 会很快填满,因此第二种选择仅适用于数量有限且大小有限的排队文件。

我不知道 RAID 和其他并行磁盘配置是否已经负责每个磁盘读取一个文件,而不是在两个磁盘上的两个文件之间来回跳转。

HTH!

【讨论】:

  • 这里的问题是,如何从同一个文件夹中读取并确保两个线程没有读取同一个文件?
  • @Sujit - ...而答案正是如此。哪部分不清楚?
  • 我不想要一个线程负责读取文件名并将文件名提供给其他线程。把它想象成一个文件夹或其他东西的锁。你知道我的意思?在您的方法中,您有一个负责入站文件的线程。我不想那样。
  • 那么你想在线程之间共享当前正在处理的文件吗?这听起来有点危险。使用 pyinotify 处理该文件夹中的文件更改事件,捕获新文件,并将它们添加到队列中,如答案所示。你不能只说“我不想”,你需要给出理由。
  • @Sujit:您不希望线程管理文件名并将文件名分发给其他线程有什么特别的原因吗?
【解决方案2】:

如果你想让多个线程直接从同一个文件夹中并行读取多个文件,那我一定让你失望了。从单个磁盘并行读取不是一个可行的选择。单个磁盘需要旋转并寻找下一个要读取的位置。如果您正在使用多个线程进行读取,那么您只是在两次查找之间弹跳磁盘,并且性能比简单的顺序读取要差得多。

只要坚持 mac 的建议,使用单线程阅读即可。

【讨论】:

  • @mac 建议中的队列包含文件名,因此多个线程可能同时从不同文件中读取。不清楚是不是比一个线程中读取所有文件慢。
  • @mac:还有文件缓存、Python 中管道数据的开销等。除非分析器另有说明,否则我会选择线程之间的较低耦合。
猜你喜欢
  • 1970-01-01
  • 2013-08-20
  • 1970-01-01
  • 2017-04-21
  • 1970-01-01
  • 1970-01-01
  • 2011-04-01
  • 2010-11-28
相关资源
最近更新 更多