基准测试:不蟒蛇有走网络文件夹的一个更快的方法?(benchmarks: does python h

2019-07-03 10:50发布

我需要通过一个文件夹与大约十万个文件走。 我的老VBScript是在处理这一非常缓慢。 自从我使用Ruby和Python从那时起开始了,我做了三个脚本语言之间的基准,看看这将是这份工作最合适的。

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

Python: 106 seconds
Ruby: 5 seconds
Vbscript: 124 seconds

这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))
'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
#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)}

编辑:因为我怀疑打印引起我测试与打印所有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

Answer 1:

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.


Answer 2:

我安装的目录结构与本地执行以下操作:

for i in $(seq 1 4500); do
    if [[ $i -lt 100 ]]; then
        dir="$(for j in $(seq 1 $i); do echo -n $i/;done)"
        mkdir -p "$dir"
        touch ${dir}$i
    else
        touch $i
    fi
done

这将创建是1-99级深,在目录结构中的根4401个文件的路径99个文件。

我用下面的Ruby脚本:

#!/usr/bin/env ruby
require 'benchmark'

def recursive(path, bench)
  bench.report(path) do
    Dir["#{path}/**/**"]
  end
end

path = 'files'
Benchmark.bm {|bench| recursive(path, bench)}

我得到了以下结果:

           user     system      total        real
    files/  0.030000   0.090000   0.120000 (  0.108562)

我用用os.walk下面的python脚本:

#!/usr/bin/env python

import os
import timeit

def path_recurse(path):
    for (path, dirs, files) in os.walk(path):
      for folder in dirs:
          yield '{}/{}'.format(path, folder)
      for filename in files:
          yield '{}/{}'.format(path, filename)

if __name__ == '__main__':
    path = 'files'
    print(timeit.timeit('[i for i in path_recurse("'+path+'")]', setup="from __main__ import path_recurse", number=1))

我得到了以下结果:

    0.250478029251

因此,它看起来像红宝石依然表现较好。 这将会是有趣的,看看这一项上的网络共享文件集的表现如何。

它很可能也是有趣的,看看这个脚本甚至pypy运行python3与Jython和可能。



文章来源: benchmarks: does python have a faster way of walking a network folder?