嘿,我正在研究一个用python编写的高性能文件管理/分析工具包。
我想创建一个函数,以树格式给我一个列表或类似的东西。
像这样的东西 问题(与java相关)
从:
dir/file
dir/dir2/file2
dir/file3
dir3/file4
dir3/file5
注意:路径列表未排序
至:
dir/
file
dir2/
file2
file3
dir3/
file4
file5
[[dir, [file, [dir2, [file2]], file3]], [dir3, [file4, file5]]]
这些方面的东西。我一直在玩一些想法,但没有一个能提供我想要的速度。
注意:我已经有了路径列表,所以不用担心。该函数采用路径列表并给出树列表。
提前致谢
既然你已经澄清了这个问题,我想以下是你想要的:
from collections import defaultdict
input_ = '''dir/file
dir/dir2/file2
dir/file3
dir2/alpha/beta/gamma/delta
dir2/alpha/beta/gamma/delta/
dir3/file4
dir3/file5'''
FILE_MARKER = '<files>'
def attach(branch, trunk):
'''
Insert a branch of directories on its trunk.
'''
parts = branch.split('/', 1)
if len(parts) == 1: # branch is a file
trunk[FILE_MARKER].append(parts[0])
else:
node, others = parts
if node not in trunk:
trunk[node] = defaultdict(dict, ((FILE_MARKER, []),))
attach(others, trunk[node])
def prettify(d, indent=0):
'''
Print the file tree structure with proper indentation.
'''
for key, value in d.iteritems():
if key == FILE_MARKER:
if value:
print ' ' * indent + str(value)
else:
print ' ' * indent + str(key)
if isinstance(value, dict):
prettify(value, indent+1)
else:
print ' ' * (indent+1) + str(value)
main_dict = defaultdict(dict, ((FILE_MARKER, []),))
for line in input_.split('\n'):
attach(line, main_dict)
prettify(main_dict)
它输出:
dir3
['file4', 'file5']
dir2
alpha
beta
gamma
['delta']
delta
['']
dir
dir2
['file2']
['file', 'file3']
有几点需要注意:
- 该脚本大量使用 defaultdicts,基本上这允许跳过检查密钥的存在及其初始化(如果不存在)
- 目录名称被映射到字典键,我认为这对您来说可能是一个很好的功能,因为密钥是经过哈希处理的,并且您可以比使用列表更快地检索信息。您可以访问表单中的层次结构
main_dict['dir2']['alpha']['beta']
...
- 注意区别
.../delta
和 .../delta/
。我认为这有助于您快速区分您的叶子是目录还是文件。
我希望这回答了你的问题。如果有任何不清楚的地方,发表评论。
我不清楚你拥有什么和你需要什么(它可能有助于提供你所拥有的那些太慢的代码),但你可能应该将你的路径名分解为dirnames和basenames,然后构建一个使用特制类的树,或者至少是列表或字典的层次结构。然后,各种遍历应该允许您以几乎任何方式进行序列化。
至于性能问题,您是否考虑过使用Pypy,Cython或Shedskin?我有一个重复数据删除备份系统,我一直在努力,可以在Pypy或Cython上运行相同的代码;在Pypy上运行它实际上优于Cython增强版本(32位上的很多,64位上的一点点)。我也喜欢比较流行皮肤,但它显然无法穿过shedskin / cpython边界。
此外,当您遇到性能问题时,分析是必要的 - 至少,如果您已经选择了适当的算法。
首先, “非常高的表现” 和 “蟒蛇” 不要混合好。如果您正在寻找的是将性能优化到极致,那么切换到C将为您带来远远优于您可能想到的任何智能代码优化的好处。
其次, 很难相信这个瓶颈 在一个 “文件管理/分析工具包” 将是这个功能。磁盘上的I / O操作至少比内存中发生的任何操作慢几个数量级。分析你的代码是衡量这一点的唯一准确方法但是...如果我错了,我准备给你一个披萨! ;)
我建立了一个愚蠢的测试功能只是为了执行一些初步测量:
from timeit import Timer as T
PLIST = [['dir', ['file', ['dir2', ['file2']], 'file3']], ['dir3', ['file4', 'file5', 'file6', 'file7']]]
def tree(plist, indent=0):
level = []
for el in plist:
if isinstance(el, list):
level.extend(tree(el, indent + 2))
else:
level.append(' ' * indent + el)
return level
print T(lambda : tree(PLIST)).repeat(number=100000)
这输出:
[1.0135619640350342, 1.0107290744781494, 1.0090651512145996]
由于测试路径列表是10个文件,并且迭代次数是100000,这意味着在1秒内您可以处理大约100万个文件的树。现在......除非你在Google工作,否则这对我来说似乎是可以接受的。
相比之下,当我开始写这个答案时,我点击了我的主要80Gb HD的根目录上的“属性”选项[这应该是给我我使用C代码的文件数量]。几分钟过去了,我大约50 GB,300000个文件......
HTH! :)