嘿,我正在开发一个用python编写的高性能文件管理/分析工具包。 我想创建一个函数,以树格式给我一个列表或类似的东西。 像question (java-related)
这样的东西自:
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]]]
沿着这些方向的东西。我一直在玩一些想法,但没有一个能提供我想要的速度。
注意:我已经有路径列表,所以不用担心。该函数采用路径列表并给出树列表。
先谢谢
答案 0 :(得分:15)
既然你已经澄清了这个问题,我想以下是你想要的:
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']
有一点需要注意:
main_dict['dir2']['alpha']['beta']
... .../delta
和.../delta/
之间的区别。我认为这有助于您快速区分作为目录或文件的叶子。我希望这能回答你的问题。如果有任何不清楚的地方,请发表评论。
答案 1 :(得分:1)
我不清楚你拥有什么和你需要什么(它可能有助于提供你所拥有的一些太慢的代码),但你可能应该将你的路径名分解为dirnames和basenames,然后使用特制的类或至少是列表或词典的层次结构来构建树。然后,各种遍历应该允许您以几乎任何方式进行序列化。
关于性能问题,你考虑过使用Pypy,Cython或Shedskin吗?我有一个重复数据删除备份系统,我一直在努力,可以在Pypy或Cython上运行相同的代码;在Pypy上运行它实际上优于Cython增强版本(32位上的很多,64位上的一点点)。我也喜欢比较流行皮草,但它显然无法在割皮/ cpython边界产生效果。
此外,如果您遇到性能问题,则需要进行性能分析 - 至少,如果您已经选择了合适的算法。
答案 2 :(得分:0)
首先, “非常高性能”和“Python”混合不好。如果您正在寻找的是将性能优化到极致,那么切换到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! :)