使用 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 可能是个问题。
题目:
- 是否有比 os.walk 更快的替代方案?
- 穿线会固定吗?
Is there a faster alternative to os.walk
?
是的。事实上,多个。
scandir
(将在 3.5 中的标准库中)比 walk
. 快得多
- C 函数
fts
明显快于 scandir
。我很确定 PyPI 上有包装器,虽然我不知道有什么值得推荐的,而且如果你知道任何 C,通过 ctypes
或 cffi
使用它并不难。
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 文件放在与您正在扫描的文件系统不同的文件系统上(或者将它保存在内存中直到完成,然后一次将其全部写入磁盘),这可能值得一试。
最后,但也是最重要的:
- 分析您的代码以查看热点在哪里,而不是猜测。
- 创建小型数据集并对不同的备选方案进行基准测试,以了解您获得了多少收益。
任务:
我正在使用 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 可能是个问题。
题目:
- 是否有比 os.walk 更快的替代方案?
- 穿线会固定吗?
Is there a faster alternative to
os.walk
?
是的。事实上,多个。
scandir
(将在 3.5 中的标准库中)比walk
. 快得多
- C 函数
fts
明显快于scandir
。我很确定 PyPI 上有包装器,虽然我不知道有什么值得推荐的,而且如果你知道任何 C,通过ctypes
或cffi
使用它并不难。 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 文件放在与您正在扫描的文件系统不同的文件系统上(或者将它保存在内存中直到完成,然后一次将其全部写入磁盘),这可能值得一试。
最后,但也是最重要的:
- 分析您的代码以查看热点在哪里,而不是猜测。
- 创建小型数据集并对不同的备选方案进行基准测试,以了解您获得了多少收益。