基准测试:python有更快的方式走网络文件夹吗?

pet*_*ter 30 ruby python vbscript benchmarking

我需要浏览一个包含大约一万个文件的文件夹.我的旧vbscript在处理这个问题时非常缓慢.从那时起我就开始使用Ruby和Python,我在三种脚本语言之间做了一个基准测试,看看哪种语言最适合这项工作.

以下测试的结果是共享网络上4500个文件的子集

Python: 106 seconds
Ruby: 5 seconds
Vbscript: 124 seconds
Run Code Online (Sandbox Code Playgroud)

Vbscript会是最慢的并不奇怪,但我无法解释Ruby和Python之间的区别.我对Python的测试不是最佳的吗?有没有更快的方法在Python中执行此操作?

thumbs.db的测试仅用于测试,实际上还有更多的测试要做.

我需要一些东西来检查路径上的每个文件,并且不会产生太多输出而不会干扰时序.结果每次运行都有点不同,但不是很多.

#python2.7.0
import os

def recurse(path):
  for (path, dirs, files) in os.walk(path):
    for file in files:
      if file.lower() == "thumbs.db":
        print (path+'/'+file)

if __name__ == '__main__':
  import timeit
  path = '//server/share/folder/'
  print(timeit.timeit('recurse("'+path+'")', setup="from __main__ import recurse", number=1))
Run Code Online (Sandbox Code Playgroud)
'vbscript5.7
set oFso = CreateObject("Scripting.FileSystemObject")
const path = "\\server\share\folder"
start = Timer
myLCfilename="thumbs.db"

sub recurse(folder)
  for each file in folder.Files
    if lCase(file.name) = myLCfilename then
      wscript.echo file
    end if
  next
  for each subfolder in folder.SubFolders
    call Recurse(subfolder)
  next
end Sub

set folder = oFso.getFolder(path)
recurse(folder)
wscript.echo Timer-start
Run Code Online (Sandbox Code Playgroud)
#ruby1.9.3
require 'benchmark'

def recursive(path, bench)
  bench.report(path) do
    Dir["#{path}/**/**"].each{|file| puts file if File.basename(file).downcase == "thumbs.db"}
  end
end

path = '//server/share/folder/'
Benchmark.bm {|bench| recursive(path, bench)}
Run Code Online (Sandbox Code Playgroud)

编辑:因为我怀疑打印导致延迟我测试脚本打印所有4500文件,也打印无,差异仍然存在,R:5 P:107在第一种情况和R:4.5 P:107在后者

EDIT2:基于这里的答案和评论,Python版本在某些情况下可以通过跳过文件夹来更快地运行

import os

def recurse(path):
  for (path, dirs, files) in os.walk(path):
    for file in files:
      if file.lower() == "thumbs.db":
        print (path+'/'+file)

def recurse2(path):
    for (path, dirs, files) in os.walk(path):
        for dir in dirs:
            if dir in ('comics'):
                dirs.remove(dir)
        for file in files:
            if file.lower() == "thumbs.db":
                print (path+'/'+file)


if __name__ == '__main__':
  import timeit
  path = 'f:/'
  print(timeit.timeit('recurse("'+path+'")', setup="from __main__ import recurse", number=1)) 
#6.20102692
  print(timeit.timeit('recurse2("'+path+'")', setup="from __main__ import recurse2", number=1)) 
#2.73848228
#ruby 5.7
Run Code Online (Sandbox Code Playgroud)

Vin*_*jip 8

Ruby实现Dir是在C(文件dir.c,根据本文档).但是,Python等价物是用Python实现.

这并不奇怪,Python是低于C性能良好,但是在Python中使用的方法提供了更多一点的灵活性-例如,你可以跳过命名如子树全'.svn','.git','.hg'在遍历目录层次结构.

大多数时候,Python实现足够快.

更新:跳过文件/子目录根本不会影响遍历,但是处理目录树所花费的总时间当然可以减少,因为您不必遍历主树的潜在大型子树.节省的时间当然与您跳过的数量成正比.在你的情况下,它看起来像图像文件夹,你不太可能节省很多时间(除非图像处于版本控制之下,当跳过修订控制系统拥有的子树可能会产生一些影响).

其他更新:通过更改dirs值来完成跳过文件夹:

for root, dirs, files in os.walk(path):
    for skip in ('.hg', '.git', '.svn', '.bzr'):
        if skip in dirs:
            dirs.remove(skip)
        # Now process other stuff at this level, i.e.
        # in directory "root". The skipped folders
        # won't be recursed into.
Run Code Online (Sandbox Code Playgroud)