使用 Python 处理许多文件

Working on many files with Python

任务:

我正在使用 4 TB data/files,存储在外部 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

问题:

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

题目:

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

Is there a faster alternative to os.walk?

是的。事实上,多个。

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

Would threading fasten things up?

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

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


还有一个想法:您可能会花费大量时间生成这些 file 进程并与之通信。有多个 Python 库使用相同的 libmagic that it does. I don't want to recommend one in particular over the others, so here's search results.


正如 monkut 所建议的,确保您正在执行批量提交,而不是使用 sqlite 自动提交每个插入。由于 the FAQ explains,sqlite 每秒可以执行约 50000 次插入,但每秒只能执行几十个事务。

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


最后,但也是最重要的:

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