我想分析文件系统并将结果打印为格式化文件。我的第一个实现可以简单地是纯文本,但在以后我想要合并HTML。
我使用基本方法收集每个文件夹中包含的文件,我可以将其返回并发送给文本处理器:
def gather_tree(source):
tree = {}
for path, dirs, files in os.walk(source):
tree[path] = []
for file in files:
tree[path].append(file)
return tree
显然,这里的问题是我正在制作一个没有深度概念的结构,我想我需要能够以足够的空间和嵌套正确地格式化列表。
我目前非常基本的打印模式如下:
def print_file_tree(tree):
# Prepare tree
dir_list = tree.keys()
dir_list.sort()
for directory in dir_list:
print directory
for f in tree[directory]:
print f
我对数据结构并不陌生,并希望得到一些意见!
答案 0 :(得分:2)
如果您计划从数据创建XML,您实际上必须创建一个树状结构。这可以是您构建,注释并可能迭代或遍历的中间树,然后转换为ElementTree
以创建XML。或者,您可以使用lxml的ElementTree API直接构建ElementTree
。
无论哪种方式,使用os.walk()
都不是可行的方法。这听起来可能违反直觉,但重点在于:os.walk()
为您序列化(展平)文件系统树,因此您可以轻松地对其进行迭代,而不必处理编写递归函数的问题。那。但是,在您的情况下,想要保留树结构,因此如果您自己编写递归函数会更容易。
这是一个使用ElementTree
构建lxml
的示例。
(此代码基于@MikeDeSimone's answer松散地基于类似问题)
import os
from lxml import etree
def dir_as_tree(path):
"""Recursive function that walks a directory and returns a tree
of nested etree nodes.
"""
basename = os.path.basename(path)
node = etree.Element("node")
node.attrib['name'] = basename
# Gather some more information on this path here
# and write it to attributes
# ...
if os.path.isdir(path):
# Recurse
node.tag = 'dir'
for item in sorted(os.listdir(path)):
item_path = os.path.join(path, item)
child_node = dir_as_tree(item_path)
node.append(child_node)
return node
else:
node.tag = 'file'
return node
# Create a tree of the current working directory
cwd = os.getcwd()
root = dir_as_tree(cwd)
# Create an element tree from the root node
# (in order to serialize it to a complete XML document)
tree = etree.ElementTree(root)
xml_document = etree.tostring(tree,
pretty_print=True,
xml_declaration=True,
encoding='utf-8')
print xml_document
示例输出:
<?xml version='1.0' encoding='utf-8'?>
<dir name="dirwalker">
<dir name="top1">
<file name="foobar.txt"/>
<dir name="sub1"/>
</dir>
<dir name="top2">
<dir name="sub2"/>
</dir>
<dir name="top3">
<dir name="sub3">
<dir name="sub_a"/>
<dir name="sub_b"/>
</dir>
</dir>
<file name="topfile1.txt"/>
<file name="walker.py"/>
</dir>