【问题标题】:Working on many files with Python使用 Python 处理许多文件
【发布时间】:2015-05-07 14:30:54
【问题描述】:

任务:

我正在处理 4 TB 的数据/文件,存储在外部 USB 磁盘上:图像、html、视频、可执行文件等。

我想使用以下架构索引 sqlite3 数据库中的所有这些文件:

path TEXT, mimetype TEXT, filetype TEXT, size INT

到目前为止:

我os.walk递归遍历挂载的目录,用python的子进程执行linuxfile命令,用os.path.getsize()获取大小。最后将结果写入数据库,存储在我的电脑上——当然,usb 是用 -o ro 挂载的。顺便说一句,没有线程

你可以在这里看到完整的代码http://hub.darcs.net/ampoffcom/smtid/browse/smtid.py

问题:

代码真的很慢。我意识到目录结构越深,代码越慢。我想,os.walk 可能是个问题。

问题:

  1. 是否有比 os.walk 更快的替代方案?
  2. 穿线会固定东西吗?

【问题讨论】:

  • 确保您进行批量提交而不是使用自动提交。
  • 如果os.walk是你的瓶颈,那么即将到来的Python 3.5有os.scandir,它基本上是一个优化的os.walk
  • 我怀疑线程在这里会有很大帮助,因为这听起来您的代码主要受 I/O 限制。
  • 如果你真的很想确定,那么你应该对它进行基准测试并找出时间的去向。如果我只是简单地推测,我猜想产生新进程的开销不小,看看guessing the file type using a libmagic binding for Python
  • 另外,我很确定有一些库可以在 PyPI 上包装 fts(几年前我自己写了一个,直到我发现一个已经完成了......),这会明显更快在大多数文件系统上都比 scandir 快(这已经比 walk 快了)。或者,如果您找不到,您可能需要子处理到find。 (是的,我给你的 file 正好相反……但在这里,它是一个做大量工作的子进程,而不是数百万只做很少工作的子进程。)

标签: python linux file sqlite subprocess


【解决方案1】:

有没有比os.walk更快的替代方案?

是的。事实上,多个。

  • scandir(将在 3.5 的 stdlib 中)明显快于 walk
  • C 函数fts 明显快于scandir。我很确定 PyPI 上有包装器,虽然我不知道有什么可以推荐的,而且如果你知道任何 C 的话,通过 ctypescffi 使用它并不难。
  • find 工具使用fts,如果您不能直接使用fts,您可以随时使用subprocess

穿线能把东西固定起来吗?

这取决于我们没有的您的系统的详细信息,但是……您将所有时间都花在等待文件系统上。除非您有多个仅在用户级别绑定在一起的独立驱动器(即,不是 LVM 或低于它的东西,如 RAID)或根本没有(例如,一个只是安装在另一个文件系统下),否则并行发出多个请求可能不会加快速度。

不过,这很容易测试;为什么不试试看呢?


还有一个想法:您可能会花费大量时间来生成和与那些file 进程通信。有多个 Python 库使用相同的 libmagic。我不想特别推荐一个,所以这里是search results


正如蒙库特建议的那样,确保您进行批量提交,而不是使用 sqlite 自动提交每个插入。正如the FAQ explains,sqlite 每秒可以进行大约 50000 次插入,但每秒只能执行几十个事务。

当我们这样做时,如果您可以将 sqlite 文件放在与您正在扫描的文件系统不同的文件系统上(或者将其保存在内存中直到完成,然后将其一次全部写入磁盘),这可能值得一试。


最后,但最重要的是:

  • 分析您的代码以查看热点在哪里,而不是猜测。
  • 创建小型数据集并对不同的替代方案进行基准测试,看看您能获得多少收益。

【讨论】:

  • 好答案!谢谢!我等了几个小时才接受,但我认为这将是最有帮助的!
猜你喜欢
  • 2011-08-22
  • 1970-01-01
  • 2016-09-02
  • 1970-01-01
  • 2017-06-18
  • 1970-01-01
  • 1970-01-01
  • 2022-06-12
  • 1970-01-01
相关资源
最近更新 更多